lixinger-python 0.1.2__tar.gz → 0.2.0__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.
Files changed (170) hide show
  1. lixinger_python-0.2.0/.claude/settings.local.json +81 -0
  2. lixinger_python-0.2.0/ADD_NEW_API_QUICK.md +203 -0
  3. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/AGENTS.md +41 -18
  4. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/CHANGELOG.md +48 -1
  5. lixinger_python-0.2.0/PKG-INFO +329 -0
  6. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/PUBLISHING.md +1 -1
  7. lixinger_python-0.2.0/README.md +303 -0
  8. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/SETUP.md +117 -7
  9. lixinger_python-0.2.0/docs/examples/company.md +55 -0
  10. lixinger_python-0.2.0/docs/getting-started/quickstart.md +368 -0
  11. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/index.md +30 -14
  12. lixinger_python-0.2.0/examples/company_example.py +41 -0
  13. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/examples/company_profile_example.py +11 -9
  14. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/__init__.py +2 -2
  15. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/base.py +12 -12
  16. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/announcement.py +4 -4
  17. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/candlestick.py +4 -4
  18. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/company.py +4 -4
  19. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/dividend.py +4 -4
  20. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/equity_change.py +4 -4
  21. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/fs/non_financial.py +4 -4
  22. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/fundamental.py +24 -24
  23. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/indices.py +4 -4
  24. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/profile.py +4 -4
  25. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/fund/announcement.py +4 -4
  26. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/fund/asset_combination.py +4 -4
  27. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/fund/asset_industry_combination.py +4 -4
  28. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/fund/candlestick.py +4 -4
  29. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/fund/fund.py +4 -4
  30. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/fund/profile.py +4 -4
  31. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/fund/shareholdings.py +4 -4
  32. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/index/candlestick.py +4 -4
  33. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/index/constituent_weightings.py +4 -4
  34. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/index/constituents.py +4 -4
  35. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/index/drawdown.py +4 -4
  36. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/index/fundamental.py +4 -4
  37. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/index/index.py +4 -4
  38. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/index/tracking_fund.py +4 -4
  39. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/client.py +15 -13
  40. lixinger_python-0.2.0/lixinger/utils/api.py +15 -0
  41. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/utils/rate_limiter.py +5 -4
  42. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/utils/retry.py +9 -9
  43. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/pyproject.toml +2 -2
  44. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/api/cn/company/test_announcement.py +13 -9
  45. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/api/cn/company/test_dividend.py +9 -6
  46. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_candlestick.py +8 -6
  47. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_client.py +15 -11
  48. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_cn_index_candlestick.py +12 -9
  49. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_cn_index_constituent_weightings.py +9 -7
  50. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_company.py +9 -7
  51. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_company_profile.py +9 -7
  52. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_equity_change.py +12 -9
  53. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_fund.py +9 -7
  54. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_fund_announcement.py +12 -9
  55. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_fund_asset_combination.py +15 -11
  56. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_fund_asset_industry_combination.py +9 -7
  57. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_fund_candlestick.py +9 -7
  58. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_fund_profile.py +9 -7
  59. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_fund_shareholdings.py +9 -7
  60. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_fundamental.py +12 -9
  61. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_index.py +9 -7
  62. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_index_constituents.py +12 -9
  63. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_index_drawdown.py +4 -3
  64. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_index_fundamental.py +12 -9
  65. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_indices.py +9 -7
  66. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_integration.py +52 -28
  67. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_non_financial_statements.py +12 -9
  68. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/test_tracking_fund.py +11 -8
  69. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/uv.lock +64 -58
  70. lixinger_python-0.1.2/.claude/settings.local.json +0 -56
  71. lixinger_python-0.1.2/ADD_NEW_API_QUICK.md +0 -150
  72. lixinger_python-0.1.2/PKG-INFO +0 -171
  73. lixinger_python-0.1.2/README.md +0 -145
  74. lixinger_python-0.1.2/docs/examples/company.md +0 -24
  75. lixinger_python-0.1.2/docs/getting-started/quickstart.md +0 -256
  76. lixinger_python-0.1.2/examples/company_example.py +0 -39
  77. lixinger_python-0.1.2/lixinger/utils/api.py +0 -15
  78. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/.env.example +0 -0
  79. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/.github/copilot-instructions.md +0 -0
  80. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/.github/workflows/README.md +0 -0
  81. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/.github/workflows/pr-checks.yml +0 -0
  82. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/.gitignore +0 -0
  83. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/.pre-commit-config.yaml +0 -0
  84. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/.python-version +0 -0
  85. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/.ruff.toml +0 -0
  86. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/CLAUDE.md +0 -0
  87. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/DOCS.md +0 -0
  88. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/LICENSE +0 -0
  89. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/MANIFEST.in +0 -0
  90. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/codecov.yml +0 -0
  91. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/client.md +0 -0
  92. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/company/announcement.md +0 -0
  93. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/company/candlestick.md +0 -0
  94. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/company/company.md +0 -0
  95. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/company/dividend.md +0 -0
  96. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/company/equity_change.md +0 -0
  97. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/company/fs/non_financial.md +0 -0
  98. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/company/fundamental.md +0 -0
  99. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/company/indices.md +0 -0
  100. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/company/profile.md +0 -0
  101. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/fund/announcement.md +0 -0
  102. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/fund/asset_combination.md +0 -0
  103. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/fund/asset_industry_combination.md +0 -0
  104. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/fund/candlestick.md +0 -0
  105. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/fund/fund.md +0 -0
  106. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/fund/profile.md +0 -0
  107. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/fund/shareholdings.md +0 -0
  108. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/index/candlestick.md +0 -0
  109. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/index/constituent_weightings.md +0 -0
  110. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/index/constituents.md +0 -0
  111. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/index/drawdown.md +0 -0
  112. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/index/fundamental.md +0 -0
  113. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/index/index.md +0 -0
  114. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/index/tracking_fund.md +0 -0
  115. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/api/overview.md +0 -0
  116. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/development/code-style.md +0 -0
  117. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/development/contributing.md +0 -0
  118. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/development/testing.md +0 -0
  119. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/examples/fund.md +0 -0
  120. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/examples/index.md +0 -0
  121. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/getting-started/configuration.md +0 -0
  122. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/docs/getting-started/installation.md +0 -0
  123. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/fund_response.json +0 -0
  124. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/__init__.py +0 -0
  125. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/__init__.py +0 -0
  126. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/__init__.py +0 -0
  127. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/fs/__init__.py +0 -0
  128. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/company/namespace.py +0 -0
  129. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/fund/__init__.py +0 -0
  130. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/api/cn/index/__init__.py +0 -0
  131. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/config.py +0 -0
  132. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/exceptions.py +0 -0
  133. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/__init__.py +0 -0
  134. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/__init__.py +0 -0
  135. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/company/__init__.py +0 -0
  136. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/company/announcement.py +0 -0
  137. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/company/candlestick.py +0 -0
  138. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/company/company.py +0 -0
  139. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/company/dividend.py +0 -0
  140. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/company/equity_change.py +0 -0
  141. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/company/fs/__init__.py +0 -0
  142. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/company/fs/non_financial.py +0 -0
  143. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/company/fundamental.py +0 -0
  144. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/company/indices.py +0 -0
  145. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/fund/__init__.py +0 -0
  146. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/fund/announcement.py +0 -0
  147. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/fund/asset_combination.py +0 -0
  148. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/fund/asset_industry_combination.py +0 -0
  149. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/fund/candlestick.py +0 -0
  150. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/fund/fund.py +0 -0
  151. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/fund/profile.py +0 -0
  152. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/fund/shareholdings.py +0 -0
  153. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/index/__init__.py +0 -0
  154. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/index/candlestick.py +0 -0
  155. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/index/constituent_weightings.py +0 -0
  156. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/index/constituents.py +0 -0
  157. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/index/drawdown.py +0 -0
  158. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/index/fundamental.py +0 -0
  159. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/index/index.py +0 -0
  160. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/models/cn/index/tracking_fund.py +0 -0
  161. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/py.typed +0 -0
  162. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/utils/__init__.py +0 -0
  163. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/utils/dataframe.py +0 -0
  164. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/lixinger/utils/dict.py +0 -0
  165. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/mkdocs.yml +0 -0
  166. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/mypy.ini +0 -0
  167. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/scripts/explore_api.py +0 -0
  168. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/scripts/generate_docs.py +0 -0
  169. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/scripts/publish.sh +0 -0
  170. {lixinger_python-0.1.2 → lixinger_python-0.2.0}/tests/conftest.py +0 -0
@@ -0,0 +1,81 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(tree -L 3 -I \".venv|venv|__pycache__|*.pyc\")",
5
+ "Bash(find . -type d -not -path ./.venv/* -not -path ./.git/*)",
6
+ "Bash(uv --version)",
7
+ "WebFetch(domain:www.lixinger.com)",
8
+ "Bash(uv add python-dotenv)",
9
+ "Bash(python -c \"from lixinger.config import get_config_from_env; print\\(''Config module loads successfully''\\)\")",
10
+ "Bash(python -c \"from lixinger import LixingerClient; print\\(''LixingerClient imports successfully''\\)\")",
11
+ "Bash(ls -la .env*)",
12
+ "Bash(python -c \"\nimport sys\nsys.path.insert\\(0, ''.''\\)\n\n# Test that api_key parameter doesn''t exist\nfrom lixinger.client import LixingerClient\nimport inspect\n\nsig = inspect.signature\\(LixingerClient.__init__\\)\nparams = list\\(sig.parameters.keys\\(\\)\\)\nprint\\(''LixingerClient.__init__ parameters:'', params\\)\nprint\\(\\)\nprint\\(''✓ api_key parameter removed!'' if ''api_key'' not in params else ''✗ api_key still exists!''\\)\nprint\\(''✓ Only keyword-only parameters remain''\\)\n\")",
13
+ "Bash(uv add --dev pre-commit)",
14
+ "Bash(uv pip install -e .)",
15
+ "Bash(python -c \"import lixinger; print\\(''✓ lixinger imports successfully''\\)\")",
16
+ "Bash(python -c \"from lixinger import LixingerClient; print\\(''✓ LixingerClient imports successfully''\\)\")",
17
+ "Bash(python -c \"import yaml; yaml.safe_load\\(open\\(''codecov.yml''\\)\\)\")",
18
+ "Bash(python3 -c \"\nimport yaml\n\nwith open\\(''codecov.yml'', ''r''\\) as f:\n config = yaml.safe_load\\(f\\)\n\nprint\\(''✅ Codecov Configuration Validation\\\\n''\\)\nprint\\(f''Project Coverage Target: {config[\"\"coverage\"\"][\"\"status\"\"][\"\"project\"\"][\"\"default\"\"][\"\"target\"\"]}''\\)\nprint\\(f''Project Threshold: {config[\"\"coverage\"\"][\"\"status\"\"][\"\"project\"\"][\"\"default\"\"][\"\"threshold\"\"]}''\\)\nprint\\(f''Patch Coverage Target: {config[\"\"coverage\"\"][\"\"status\"\"][\"\"patch\"\"][\"\"default\"\"][\"\"target\"\"]}''\\)\nprint\\(f''Patch Threshold: {config[\"\"coverage\"\"][\"\"status\"\"][\"\"patch\"\"][\"\"default\"\"][\"\"threshold\"\"]}''\\)\nprint\\(f''\\\\nFlags Configured: {list\\(config[\"\"flags\"\"].keys\\(\\)\\)}''\\)\nprint\\(f''Components: {len\\(config[\"\"component_management\"\"][\"\"individual_components\"\"]\\)} defined''\\)\nprint\\(f''GitHub Annotations: {config[\"\"github_checks\"\"][\"\"annotations\"\"]}''\\)\nprint\\(f''\\\\n✅ All fields are valid!''\\)\n\")",
19
+ "Bash(curl --data-binary @codecov.yml https://codecov.io/validate)",
20
+ "WebFetch(domain:docs.codecov.com)",
21
+ "WebSearch",
22
+ "Bash(python3 -c \"import yaml; yaml.safe_load\\(open\\(''''codecov.yml''''\\)\\)\")",
23
+ "Bash(ls -1 codecov.yml docs/CODECOV*.md)",
24
+ "Bash(curl -s --data-binary @codecov.yml https://codecov.io/validate)",
25
+ "Bash(uv run ruff check /Users/JianGuo/Documents/CursorProject/lixinger-python/AGENTS.md)",
26
+ "Bash(ls -la /Users/JianGuo/Documents/CursorProject/lixinger-python/*.md)",
27
+ "Bash(tree /Users/JianGuo/Documents/CursorProject/lixinger-python/lixinger/api -L 3)",
28
+ "Bash(tree /Users/JianGuo/Documents/CursorProject/lixinger-python/lixinger/models -L 3)",
29
+ "Bash(uv run pytest tests/ -m \"not integration\" -v)",
30
+ "Bash(uv run ruff check lixinger/)",
31
+ "Bash(uv run mypy lixinger/)",
32
+ "Bash(uv run pytest tests/ -m \"not integration\" --tb=short)",
33
+ "Bash(tree /Users/JianGuo/Documents/CursorProject/lixinger-python/lixinger -L 4 -I __pycache__)",
34
+ "Bash(uv run ruff check .)",
35
+ "Bash(find /Users/JianGuo/Documents/CursorProject/lixinger-python/examples -name *.py)",
36
+ "Bash(tree /Users/JianGuo/Documents/CursorProject/lixinger-python/lixinger -L 4 -I '__pycache__|*.pyc' --dirsfirst)",
37
+ "Bash(uv run pytest tests/ -m \"not integration\" --tb=short -q)",
38
+ "Bash(uv run pytest tests/ -m \"not integration\" -q)",
39
+ "Bash(uv add:*)",
40
+ "Bash(uv run python:*)",
41
+ "Bash(uv run mkdocs build:*)",
42
+ "Bash(git check-ignore:*)",
43
+ "Bash(uv run pytest:*)",
44
+ "Bash(uv run ruff check:*)",
45
+ "Bash(uv run ruff format:*)",
46
+ "Bash(lsof:*)",
47
+ "Bash(xargs kill:*)",
48
+ "Bash(chmod +x scripts/publish.sh)",
49
+ "Bash(chmod +x scripts/check_before_publish.py)",
50
+ "Bash(uv run twine check dist/*)",
51
+ "Bash(unzip -l dist/lixinger_python-0.1.0-py3-none-any.whl | head -30)",
52
+ "Bash(find lixinger -type f -name \"*.py\" -exec grep -l \"^import pandera as pa\" {} \\\\;)",
53
+ "Bash(find lixinger -type f -name \"*.py\" -exec sed -i '' 's/^import pandera as pa$/import pandera.pandas as pa/' {} \\\\;)",
54
+ "Bash(uv pip list 2>/dev/null | grep -E \"\\(pandas|llama\\)\" || echo \"No packages found\")",
55
+ "Bash(uv pip index versions llama-index 2>/dev/null | head -20 || echo \"Checking package info...\")",
56
+ "Bash(pip index versions llama-index 2>&1 | head -5 || uv pip show llama-index 2>&1 | head -10 || echo \"Checking...\")",
57
+ "WebFetch(domain:pypi.org)",
58
+ "Bash(curl -s \"https://pypi.org/pypi/llama-index/0.14.15/json\" | python3 -c \"import json,sys; data=json.load\\(sys.stdin\\); deps=[d for d in data['info'].get\\('requires_dist',[]\\) if 'pandas' in d.lower\\(\\)]; print\\('\\\\n'.join\\(deps\\) if deps else 'No pandas dependency'\\)\")",
59
+ "Bash(curl -s \"https://pypi.org/pypi/llama-index-readers-file/0.5.6/json\" | python3 -c \"import json,sys; data=json.load\\(sys.stdin\\); deps=[d for d in data['info'].get\\('requires_dist',[]\\) if 'pandas' in d.lower\\(\\)]; print\\('\\\\n'.join\\(deps\\) if deps else 'No pandas dependency'\\)\")",
60
+ "Bash(uv sync)",
61
+ "Bash(wc -l /Users/JianGuo/Documents/CursorProject/lixinger-python/tests/*.py | tail -1)",
62
+ "Bash(uv pip list | grep -E \"pytest|asyncio\")",
63
+ "Bash(uv run mypy lixinger/utils/)",
64
+ "Bash(uv run mypy lixinger/api/base.py)",
65
+ "Bash(uv run mypy lixinger/api/cn/)",
66
+ "Bash(uv run mypy lixinger/client.py)",
67
+ "Bash(python3 -c \"from lixinger import AsyncLixingerClient; print\\('✅ AsyncLixingerClient imported'\\)\")",
68
+ "Bash(python3 -c \"from lixinger import LixingerClient\" 2>&1 || echo \"✅ LixingerClient correctly removed\")",
69
+ "Bash(grep -l \"LixingerClient\\\\|with client\\\\|client\\\\.company\\\\.get\" --include=\"*.md\" -r . 2>/dev/null | grep -v \".venv\" | grep -v \"site/\" | grep -v \".git/\" | head -20)",
70
+ "Bash(grep -n \"from lixinger import\\\\|LixingerClient\\\\|with client\\\\|def main\" docs/getting-started/quickstart.md docs/index.md docs/examples/*.md 2>/dev/null | head -40)",
71
+ "Bash(cat > /tmp/async_docs_update_summary.md << 'EOF'\n# 异步文档更新总结\n\n## ✅ 已完成更新的文件\n\n### 核心文档\n1. **README.md** - 完全重写,展示异步特性\n2. **SETUP.md** - 更新所有示例为 async/await\n3. **CHANGELOG.md** - 添加 v2.0.0 迁移指南\n4. **AGENTS.md** - 强调 async 要求,更新所有示例\n5. **ADD_NEW_API_QUICK.md** - 所有模板改为 async\n\n### 开发指南\n6. **docs/getting-started/quickstart.md** - 完全重写为异步版本\n - 添加醒目的异步警告\n - 所有示例使用 asyncio.run\\(main\\(\\)\\)\n - 新增并发请求示例\n - 新增 Jupyter 用法说明\n\n7. **docs/index.md** - 更新首页示例为异步\n\n### 示例文件\n8. **examples/company_example.py** - 异步版本\n9. **examples/company_profile_example.py** - 异步版本\n\n## ⚠️ 需要检查的文件\n\n以下文件可能包含同步代码示例,需要批量更新:\n\n### API 文档(自动生成部分)\n- `docs/api/company/*.md` \\(9个文件\\)\n- `docs/api/index/*.md` \\(7个文件\\)\n- `docs/api/fund/*.md` \\(7个文件\\)\n\n**处理建议**: 这些文件由 mkdocstrings 自动生成,只要源码的 docstrings 是正确的(已完成),重新生成文档即可。\n\n### 示例文档\n- `docs/examples/company.md`\n- `docs/examples/fund.md`\n- `docs/examples/index.md`\n\n### 其他配置文档\n- `docs/getting-started/configuration.md`\n- `docs/getting-started/installation.md`\n\n## 🔧 修复步骤\n\n### 方法1:重新生成 API 文档(推荐)\n```bash\nuv run python scripts/generate_docs.py\n```\n这会基于最新的 docstrings 重新生成所有 API 文档。\n\n### 方法2:手动修复剩余文件\n逐个检查并更新 docs/examples/*.md 等手写文档文件。\n\n## 📋 检查清单\n\n- [x] README.md\n- [x] SETUP.md\n- [x] CHANGELOG.md\n- [x] AGENTS.md\n- [x] ADD_NEW_API_QUICK.md\n- [x] docs/getting-started/quickstart.md\n- [x] docs/index.md\n- [x] examples/*.py\n- [ ] docs/examples/*.md \\(3个\\)\n- [ ] docs/getting-started/configuration.md\n- [ ] docs/getting-started/installation.md\n- [ ] docs/api/*/*.md \\(重新生成\\)\n\n## 🎯 关键改进点\n\n所有更新的文档都包含:\n1. ✅ 使用 `AsyncLixingerClient` 而不是 `LixingerClient`\n2. ✅ 使用 `async def main\\(\\)` 包装代码\n3. ✅ 使用 `async with` 上下文管理器\n4. ✅ 所有 API 调用前加 `await`\n5. ✅ 使用 `asyncio.run\\(main\\(\\)\\)` 运行\n6. ✅ 说明 Jupyter 可以直接使用 await\n7. ✅ 展示并发请求示例(where appropriate)\nEOF\ncat /tmp/async_docs_update_summary.md)",
72
+ "Bash(ls -lah scripts/*.py | grep -E \"\\(convert|fix\\)\")",
73
+ "Bash(ls -1 scripts/*.py)",
74
+ "Bash(grep -rn \"client\\\\.company\\\\.get_company\\\\|client\\\\.company\\\\.get_profile\" --include=\"*.md\" . 2>/dev/null | grep -v \".venv\\\\|site\\\\|.git\" | head -20)",
75
+ "Bash(cat > /tmp/fix_api_paths.sh << 'EOF'\n#!/bin/bash\n# Fix incorrect API paths in documentation\n\n# Find all markdown files \\(excluding .venv, site, .git\\)\nfind . -name \"*.md\" -type f ! -path \"./.venv/*\" ! -path \"./site/*\" ! -path \"./.git/*\" | while read file; do\n # Check if file contains the incorrect patterns\n if grep -q \"client\\\\.company\\\\.get_company\\\\|client\\\\.company\\\\.get_profile\" \"$file\"; then\n echo \"Fixing: $file\"\n \n # Fix get_company\n sed -i '' 's/client\\\\.company\\\\.get_company/client.company.company.get_company/g' \"$file\"\n \n # Fix get_profile\n sed -i '' 's/client\\\\.company\\\\.get_profile/client.company.profile.get_profile/g' \"$file\"\n fi\ndone\n\necho \"Done!\"\nEOF\n\nchmod +x /tmp/fix_api_paths.sh\n/tmp/fix_api_paths.sh)",
76
+ "Bash(grep -rn \"client\\\\.company\\\\.get_company\\\\|client\\\\.company\\\\.get_profile\" --include=\"*.md\" . 2>/dev/null | grep -v \".venv\\\\|site\\\\|.git\\\\|\\\\.company\\\\.company\\\\|\\\\.company\\\\.profile\" | head -5)",
77
+ "Bash(cat > /tmp/api_path_fix_summary.md << 'EOF'\n# API 路径修复总结\n\n## 🐛 发现的问题\n\n文档中使用了错误的 API 调用路径:\n\n### ❌ 错误示例\n```python\nclient.company.get_company\\(...\\) # 错误!\nclient.company.get_profile\\(...\\) # 错误!\n```\n\n### ✅ 正确示例\n```python\nclient.company.company.get_company\\(...\\) # 正确\nclient.company.profile.get_profile\\(...\\) # 正确\n```\n\n## 📐 客户端结构\n\n```python\nAsyncLixingerClient\n├── company \\(CompanyNamespace\\)\n│ ├── company \\(CompanyAPI\\)\n│ │ └── get_company\\(\\)\n│ ├── profile \\(CompanyProfileAPI\\)\n│ │ └── get_profile\\(\\)\n│ ├── fundamental \\(FundamentalAPI\\)\n│ │ ├── get_non_financial\\(\\)\n│ │ ├── get_bank\\(\\)\n│ │ └── ...\n│ ├── candlestick \\(CandlestickAPI\\)\n│ ├── equity_change \\(EquityChangeAPI\\)\n│ ├── fs\n│ │ └── non_financial \\(NonFinancialStatementAPI\\)\n│ ├── indices \\(IndicesAPI\\)\n│ ├── dividend \\(DividendAPI\\)\n│ └── announcement \\(AnnouncementAPI\\)\n│\n├── cn_index \\(IndexAPI\\)\n├── cn_index_constituents \\(ConstituentsAPI\\)\n└── ...\n```\n\n## ✅ 修复的文件(7个)\n\n1. **README.md** - 5处修复\n - 基础用法示例\n - 并发请求示例\n - Jupyter 用法\n - Import 示例\n\n2. **SETUP.md** - 4处修复\n - 使用示例\n - 配置覆盖\n - Jupyter 示例\n - 测试示例\n\n3. **CHANGELOG.md** - 2处修复\n - v0.x 示例\n - v2.0 迁移示例\n\n4. **docs/getting-started/quickstart.md** - 3处修复\n - 并发查询示例\n - 客户端配置示例\n - Jupyter 用法\n\n5. **docs/index.md** - 1处修复\n - Jupyter 使用示例\n\n6. **docs/examples/company.md** - 3处修复\n - 并发查询示例\n\n7. **PUBLISHING.md** - 1处修复\n - 示例代码\n\n## 🎯 正确的 API 调用模式\n\n### Company APIs\n```python\n# Company information\nawait client.company.company.get_company\\(stock_codes=[\"000001\"]\\)\n\n# Company profile \nawait client.company.profile.get_profile\\(stock_codes=[\"000001\"]\\)\n\n# Fundamental data\nawait client.company.fundamental.get_non_financial\\(\n stock_codes=[\"000001\"],\n metrics=[\"pe\", \"pb\"]\n\\)\n\n# Candlestick data\nawait client.company.candlestick.get_candlestick\\(...\\)\n\n# Equity change\nawait client.company.equity_change.get_equity_change\\(...\\)\n\n# Financial statements\nawait client.company.fs.non_financial.get_non_financial_statements\\(...\\)\n\n# Indices membership\nawait client.company.indices.get_indices\\(...\\)\n\n# Dividend\nawait client.company.dividend.get_dividend\\(...\\)\n\n# Announcements\nawait client.company.announcement.get_announcement\\(...\\)\n```\n\n### Index APIs\n```python\n# 使用扁平访问(旧版兼容)\nawait client.cn_index.get_index\\(...\\)\nawait client.cn_index_constituents.get_constituents\\(...\\)\nawait client.cn_index_candlestick.get_candlestick\\(...\\)\n```\n\n### Fund APIs\n```python\n# 使用扁平访问(旧版兼容)\nawait client.cn_fund.get_fund\\(...\\)\nawait client.cn_fund_profile.get_profile\\(...\\)\nawait client.cn_fund_candlestick.get_candlestick\\(...\\)\n```\n\n## 📊 修复统计\n\n- **文件数量**: 7个文档文件\n- **修复点**: 19处 API 调用路径\n- **覆盖范围**: \n - ✅ README.md\n - ✅ SETUP.md \n - ✅ CHANGELOG.md\n - ✅ 快速入门文档\n - ✅ 首页文档\n - ✅ 示例文档\n - ✅ 发布文档\n\n## ✨ 验证\n\n所有修复后的代码现在都使用正确的 API 路径:\n- `client.company.company.get_company\\(\\)` ✅\n- `client.company.profile.get_profile\\(\\)` ✅\n- `client.company.fundamental.get_non_financial\\(\\)` ✅\n\n用户现在可以直接复制文档中的代码并成功运行!\nEOF\ncat /tmp/api_path_fix_summary.md)",
78
+ "Bash(grep -rn \"client\\\\.[a-z_]*\\\\.\\\\\\(get_\\\\|fetch_\\\\\\)\" --include=\"*.md\" README.md SETUP.md docs/getting-started/quickstart.md 2>/dev/null | grep -v \"company\\\\.company\\\\|company\\\\.profile\\\\|company\\\\.fundamental\\\\|company\\\\.candlestick\\\\|company\\\\.equity_change\\\\|company\\\\.fs\\\\|company\\\\.indices\\\\|company\\\\.dividend\\\\|company\\\\.announcement\\\\|cn_index\\\\|cn_fund\" | head -10)"
79
+ ]
80
+ }
81
+ }
@@ -0,0 +1,203 @@
1
+ # 📚 添加新 API - 快速参考
2
+
3
+ ## ⚠️ 重要:SDK 采用完全异步架构
4
+
5
+ 所有 API 方法必须使用 `async def` 并用 `await` 调用。
6
+
7
+ ## 🎯 三步添加新 API
8
+
9
+ ### 1️⃣ 写代码 + Docstrings
10
+
11
+ ```python
12
+ # lixinger/api/cn/company/your_api.py
13
+
14
+ class YourAPI(BaseAPI):
15
+ """Your API description."""
16
+
17
+ async def get_data(
18
+ self,
19
+ stock_code: str,
20
+ param: str | None = None,
21
+ ) -> pd.DataFrame:
22
+ """一行描述.
23
+
24
+ Args:
25
+ stock_code: 股票代码
26
+ param: 参数说明
27
+
28
+ Returns:
29
+ 返回值说明
30
+
31
+ Example:
32
+ >>> import asyncio
33
+ >>> async def main():
34
+ ... client = AsyncLixingerClient()
35
+ ... df = await client.your_api.get_data("000001")
36
+ >>> asyncio.run(main())
37
+
38
+ """
39
+ # 使用 await 调用 _request
40
+ data = await self._request("POST", "/endpoint", json=payload)
41
+ return get_response_df(data, Model)
42
+ ```
43
+
44
+ **关键**:
45
+ - ✅ 使用 `async def` 定义所有方法
46
+ - ✅ 使用 `await self._request(...)`
47
+ - ✅ 使用 **Google-style docstrings** + 完整**类型注解**
48
+ - ✅ Example 中展示 async/await 用法
49
+
50
+ ---
51
+
52
+ ### 2️⃣ 生成文档
53
+
54
+ **方式 A: 自动生成(推荐)**
55
+
56
+ ```bash
57
+ # 1. 编辑 scripts/generate_docs.py,添加配置
58
+ vim scripts/generate_docs.py
59
+
60
+ # 2. 运行生成脚本
61
+ uv run python scripts/generate_docs.py
62
+ ```
63
+
64
+ **方式 B: 手动创建**
65
+
66
+ ```bash
67
+ # 创建文档文件
68
+ cat > docs/api/company/your_api.md << 'EOF'
69
+ # API 名称
70
+
71
+ ## 类参考
72
+
73
+ ::: lixinger.api.cn.company.your_api.YourAPI
74
+ options:
75
+ show_root_heading: true
76
+ show_source: true
77
+ EOF
78
+ ```
79
+
80
+ ---
81
+
82
+ ### 3️⃣ 预览 & 部署
83
+
84
+ ```bash
85
+ # 本地预览
86
+ uv run mkdocs serve
87
+
88
+ # 部署到线上
89
+ uv run mkdocs gh-deploy
90
+ ```
91
+
92
+ ---
93
+
94
+ ## ✅ 检查清单
95
+
96
+ 添加新 API 时确保:
97
+
98
+ - [ ] **所有方法使用 `async def`**
99
+ - [ ] **所有 `_request` 调用使用 `await`**
100
+ - [ ] 代码使用 Google-style docstrings
101
+ - [ ] 包含 `Args`, `Returns`, `Example` 部分
102
+ - [ ] **Example 展示 async/await 用法**
103
+ - [ ] 完整的类型注解(`str`, `int | None`, `pd.DataFrame` 等)
104
+ - [ ] 运行了文档生成脚本或手动创建了文档页面
105
+ - [ ] 本地预览文档正常:`uv run mkdocs serve`
106
+ - [ ] **测试函数使用 `async def` 和 `@pytest.mark.asyncio`**
107
+
108
+ ---
109
+
110
+ ## 🔑 关键点
111
+
112
+ ### ✅ DO (推荐做法)
113
+
114
+ ```python
115
+ async def get_data(self, code: str) -> pd.DataFrame:
116
+ """获取数据.
117
+
118
+ Args:
119
+ code: 股票代码
120
+
121
+ Returns:
122
+ 数据 DataFrame
123
+
124
+ Example:
125
+ >>> import asyncio
126
+ >>> async def main():
127
+ ... df = await get_data("000001")
128
+ >>> asyncio.run(main())
129
+
130
+ """
131
+ data = await self._request("POST", "/endpoint", json={"code": code})
132
+ return get_response_df(data, Model)
133
+ ```
134
+
135
+ ### ❌ DON'T (避免)
136
+
137
+ ```python
138
+ def get_data(self, code): # ❌ 缺少 async、类型注解
139
+ """Get data.""" # ❌ Docstring 太简单、缺少 Example
140
+ # ❌ 缺少 await
141
+ data = self._request("POST", "/endpoint", json={"code": code})
142
+ return data
143
+ ```
144
+
145
+ ---
146
+
147
+ ## 📖 Docstring 最小模板
148
+
149
+ ```python
150
+ async def method_name(param: type) -> return_type:
151
+ """一行简短描述.
152
+
153
+ Args:
154
+ param: 参数说明
155
+
156
+ Returns:
157
+ 返回值说明
158
+
159
+ Example:
160
+ >>> import asyncio
161
+ >>> async def main():
162
+ ... result = await method_name("value")
163
+ >>> asyncio.run(main())
164
+
165
+ """
166
+ data = await self._request("POST", "/endpoint", json={"param": param})
167
+ return data
168
+ ```
169
+
170
+ ---
171
+
172
+ ## 🧪 测试模板
173
+
174
+ ```python
175
+ import pytest
176
+
177
+ @pytest.mark.asyncio
178
+ async def test_your_api(monkeypatch):
179
+ """测试你的 API."""
180
+
181
+ # Mock async _request
182
+ async def mock_request(*args, **kwargs):
183
+ return [{"field": "value"}]
184
+
185
+ monkeypatch.setattr(YourAPI, "_request", mock_request)
186
+ monkeypatch.setenv("LIXINGER_API_KEY", "test_key")
187
+
188
+ # 使用 await 调用
189
+ client = AsyncLixingerClient()
190
+ df = await client.your_api.get_data("000001")
191
+
192
+ assert not df.empty
193
+ ```
194
+
195
+ ---
196
+
197
+ ## 🔗 完整文档
198
+
199
+ 详细指南请查看:[ADD_NEW_API.md](ADD_NEW_API.md)
200
+
201
+ ---
202
+
203
+ **重点**:只要写好 docstrings,文档会自动生成!✨
@@ -7,6 +7,14 @@ Instructions for LLM agents implementing the Lixinger API Python SDK.
7
7
  - **API Docs**: <https://www.lixinger.com/open/api/doc>
8
8
  - **Code Examples**: See `lixinger/api/` and `lixinger/models/` for patterns
9
9
 
10
+ ## Architecture
11
+
12
+ **⚠️ IMPORTANT: This SDK is fully async/await based.**
13
+
14
+ - All API methods are `async def` and must be awaited
15
+ - Uses `httpx.AsyncClient` for non-blocking I/O
16
+ - Perfect for AI agents, Jupyter notebooks, and async web frameworks
17
+
10
18
  ## Critical: API Response Format
11
19
 
12
20
  All responses follow this format:
@@ -31,10 +39,10 @@ All responses follow this format:
31
39
 
32
40
  ```python
33
41
  # ✅ Correct
34
- client = LixingerClient()
42
+ client = AsyncLixingerClient()
35
43
 
36
44
  # ❌ Wrong - will raise TypeError
37
- client = LixingerClient(api_key="key")
45
+ client = AsyncLixingerClient(api_key="key")
38
46
  ```
39
47
 
40
48
  **Optional env vars:** `LIXINGER_BASE_URL`, `LIXINGER_TIMEOUT`, `LIXINGER_MAX_RETRIES`, `LIXINGER_PROXY`, `LIXINGER_MAX_REQUESTS_PER_MINUTE`
@@ -127,6 +135,7 @@ curl -X POST https://open.lixinger.com/api/cn/company \
127
135
 
128
136
  2. **API class** (`lixinger/api/cn/{endpoint}/`)
129
137
  - Inherit from `BaseAPI`
138
+ - **All methods MUST be async** (`async def`)
130
139
  - **Method parameters MUST match API documentation exactly**
131
140
  - Add docstring with:
132
141
  - Endpoint URL
@@ -134,10 +143,11 @@ curl -X POST https://open.lixinger.com/api/cn/company \
134
143
  - Parameter descriptions from docs
135
144
  - Use proper type hints (match API docs)
136
145
  - **Validate parameters against documented constraints**
146
+ - All API calls use `await self._request(...)`
137
147
  - Add `__init__.py` with exports
138
148
 
139
149
  3. **Integrate**
140
- - Add to `LixingerClient` in `client.py`
150
+ - Add to `AsyncLixingerClient` in `client.py`
141
151
  - Export in `lixinger/__init__.py`
142
152
 
143
153
  **Compliance Checklist:**
@@ -152,13 +162,18 @@ curl -X POST https://open.lixinger.com/api/cn/company \
152
162
  ### 3. Add Tests
153
163
 
154
164
  **Unit tests** (`tests/test_*.py`):
165
+ - **All test functions MUST be async** (`async def test_...()`)
166
+ - Add `@pytest.mark.asyncio` decorator to all async tests
167
+ - Use `await` for all API calls
155
168
  - Mock with full `{code, message, data}` format
169
+ - Mock `_request` as async: `async def mock_request(...)`
156
170
  - Test success, errors, edge cases
157
171
  - Use `monkeypatch.setenv("LIXINGER_API_KEY", "test_key")`
158
172
 
159
173
  **Integration tests** (`tests/test_integration.py`):
160
174
  - Mark with `@pytest.mark.integration`
161
- - Test with real API
175
+ - Use `async with AsyncLixingerClient() as client:`
176
+ - Test with real API using `await`
162
177
 
163
178
  **Coverage:** >80% on new code
164
179
 
@@ -175,7 +190,7 @@ uv run pytest --cov=lixinger --cov-report=term-missing -m "not integration"
175
190
  All public methods **MUST** have complete Google-style docstrings:
176
191
 
177
192
  ```python
178
- def get_data(
193
+ async def get_data(
179
194
  self,
180
195
  stock_code: str,
181
196
  start_date: str | None = None,
@@ -205,19 +220,23 @@ def get_data(
205
220
  Example:
206
221
  获取平安银行的市盈率和市净率:
207
222
 
208
- >>> client = LixingerClient()
209
- >>> df = client.company.data.get_data(
210
- ... stock_code="000001",
211
- ... start_date="2023-01-01",
212
- ... metrics=["pe", "pb"]
213
- ... )
214
- >>> print(df.head())
223
+ >>> import asyncio
224
+ >>> async def main():
225
+ ... client = AsyncLixingerClient()
226
+ ... df = await client.company.data.get_data(
227
+ ... stock_code="000001",
228
+ ... start_date="2023-01-01",
229
+ ... metrics=["pe", "pb"]
230
+ ... )
231
+ ... print(df.head())
232
+ >>> asyncio.run(main())
215
233
 
216
234
  Note:
217
235
  API 限制每分钟最多 1000 次请求。
218
236
 
219
237
  """
220
- pass
238
+ data = await self._request("POST", "/cn/company/data", json=payload)
239
+ return get_response_df(data, DataModel)
221
240
  ```
222
241
 
223
242
  **Required Sections**:
@@ -251,13 +270,17 @@ API_DOCS = {
251
270
  "endpoint": "POST /cn/company/your-api",
252
271
  "module": "lixinger.api.cn.company.your_api.YourAPI",
253
272
  "example": """```python
254
- from lixinger import LixingerClient
273
+ import asyncio
274
+ from lixinger import AsyncLixingerClient
275
+
276
+ async def main():
277
+ client = AsyncLixingerClient()
255
278
 
256
- client = LixingerClient()
279
+ # 使用示例
280
+ df = await client.company.your_api.get_data("000001")
281
+ print(df)
257
282
 
258
- # 使用示例
259
- df = client.company.your_api.get_data("000001")
260
- print(df)
283
+ asyncio.run(main())
261
284
  ```""",
262
285
  "doc_url": "https://www.lixinger.com/open/api/doc?api-key=cn/company/your-api",
263
286
  },
@@ -10,7 +10,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
10
10
  ### Planned
11
11
  - Add support for US stock market APIs
12
12
  - Add caching mechanism for API responses
13
- - Add async support
13
+
14
+ ## [0.2.0] - 2026-02-26
15
+
16
+ ### ⚠️ BREAKING CHANGES
17
+
18
+ This release completely migrates the SDK to async/await. All existing code must be updated.
19
+
20
+ **Migration Guide:**
21
+
22
+ ```python
23
+ # v0.1.x (old - blocking)
24
+ from lixinger import LixingerClient
25
+
26
+ with LixingerClient() as client:
27
+ df = client.company.company.get_company(["000001"])
28
+
29
+ # v0.2.0 (new - async)
30
+ import asyncio
31
+ from lixinger import AsyncLixingerClient
32
+
33
+ async def main():
34
+ async with AsyncLixingerClient() as client:
35
+ df = await client.company.company.get_company(["000001"])
36
+
37
+ asyncio.run(main())
38
+ ```
39
+
40
+ ### Changed
41
+ - **BREAKING**: `LixingerClient` renamed to `AsyncLixingerClient`
42
+ - **BREAKING**: All API methods now return coroutines and must be awaited
43
+ - **BREAKING**: Context manager now requires `async with` instead of `with`
44
+ - **BREAKING**: `client.close()` is now async and must be awaited
45
+ - **BREAKING**: All functional APIs (e.g., `get_company()`) are now async
46
+ - Replaced `httpx.Client` with `httpx.AsyncClient`
47
+ - Replaced `time.sleep` with `asyncio.sleep` in rate limiter and retry logic
48
+
49
+ ### Added
50
+ - ✨ Full async/await support throughout the SDK
51
+ - ✨ Concurrent request capability - query multiple stocks in parallel
52
+ - ✨ Native Jupyter Notebook support (top-level await)
53
+ - ✨ Perfect integration with AI Agent frameworks (LangChain, LlamaIndex)
54
+ - ✨ Compatible with async web frameworks (FastAPI, Sanic, Quart)
55
+
56
+ ### Benefits
57
+ - Non-blocking I/O for better performance in async contexts
58
+ - Ability to query multiple stocks concurrently using `asyncio.gather()`
59
+ - Seamless integration with modern Python async ecosystem
60
+ - Ideal for AI agents that need to fetch financial data without blocking
14
61
 
15
62
  ## [0.1.0] - 2026-02-24
16
63