lib-x17-fintech 2.1.3__py3-none-any.whl

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 (282) hide show
  1. lib_x17_fintech-2.1.3.dist-info/METADATA +633 -0
  2. lib_x17_fintech-2.1.3.dist-info/RECORD +282 -0
  3. lib_x17_fintech-2.1.3.dist-info/WHEEL +5 -0
  4. lib_x17_fintech-2.1.3.dist-info/licenses/LICENSE +1 -0
  5. lib_x17_fintech-2.1.3.dist-info/top_level.txt +1 -0
  6. xfintech/__init__.py +0 -0
  7. xfintech/connect/__init__.py +18 -0
  8. xfintech/connect/artifact/__init__.py +5 -0
  9. xfintech/connect/artifact/artifact.py +168 -0
  10. xfintech/connect/artifact/tests/__init__.py +3 -0
  11. xfintech/connect/artifact/tests/test_class_artifact_all.py +564 -0
  12. xfintech/connect/common/__init__.py +12 -0
  13. xfintech/connect/common/connect.py +49 -0
  14. xfintech/connect/common/connectref.py +119 -0
  15. xfintech/connect/common/error.py +62 -0
  16. xfintech/connect/common/tests/__init__.py +1 -0
  17. xfintech/connect/common/tests/test_class_connectlike_all.py +544 -0
  18. xfintech/connect/common/tests/test_class_connectref_all.py +586 -0
  19. xfintech/connect/common/tests/test_class_errors_all.py +524 -0
  20. xfintech/connect/instance/__init__.py +7 -0
  21. xfintech/connect/instance/macos.py +121 -0
  22. xfintech/connect/instance/s3.py +176 -0
  23. xfintech/connect/instance/tests/__init__.py +1 -0
  24. xfintech/connect/instance/tests/test_class_macosconnect_all.py +692 -0
  25. xfintech/connect/instance/tests/test_class_s3connect_all.py +603 -0
  26. xfintech/data/__init__.py +20 -0
  27. xfintech/data/common/__init__.py +15 -0
  28. xfintech/data/common/cache.py +186 -0
  29. xfintech/data/common/coolant.py +171 -0
  30. xfintech/data/common/metric.py +138 -0
  31. xfintech/data/common/paginate.py +132 -0
  32. xfintech/data/common/params.py +162 -0
  33. xfintech/data/common/retry.py +201 -0
  34. xfintech/data/common/tests/__init__.py +1 -0
  35. xfintech/data/common/tests/test_class_cache_all.py +681 -0
  36. xfintech/data/common/tests/test_class_coolant_all.py +534 -0
  37. xfintech/data/common/tests/test_class_metric_all.py +705 -0
  38. xfintech/data/common/tests/test_class_paginate_all.py +508 -0
  39. xfintech/data/common/tests/test_class_params_all.py +891 -0
  40. xfintech/data/common/tests/test_class_retry_all.py +714 -0
  41. xfintech/data/job/__init__.py +17 -0
  42. xfintech/data/job/errors.py +112 -0
  43. xfintech/data/job/house.py +156 -0
  44. xfintech/data/job/job.py +247 -0
  45. xfintech/data/job/joblike.py +47 -0
  46. xfintech/data/job/tests/__init__.py +1 -0
  47. xfintech/data/job/tests/test_class_errors_all.py +275 -0
  48. xfintech/data/job/tests/test_class_house_all.py +801 -0
  49. xfintech/data/job/tests/test_class_job_all.py +684 -0
  50. xfintech/data/job/tests/test_class_joblike_all.py +482 -0
  51. xfintech/data/relay/__init__.py +7 -0
  52. xfintech/data/relay/client.py +114 -0
  53. xfintech/data/relay/clientlike.py +45 -0
  54. xfintech/data/relay/tests/test_class_relayclient_all.py +484 -0
  55. xfintech/data/relay/tests/test_class_relayclientlike_all.py +500 -0
  56. xfintech/data/source/__init__.py +7 -0
  57. xfintech/data/source/baostock/__init__.py +21 -0
  58. xfintech/data/source/baostock/job/__init__.py +5 -0
  59. xfintech/data/source/baostock/job/job.py +217 -0
  60. xfintech/data/source/baostock/job/tests/__init__.py +0 -0
  61. xfintech/data/source/baostock/job/tests/test_class_baostockjob_all.py +547 -0
  62. xfintech/data/source/baostock/session/__init__.py +8 -0
  63. xfintech/data/source/baostock/session/relay.py +223 -0
  64. xfintech/data/source/baostock/session/session.py +241 -0
  65. xfintech/data/source/baostock/session/tests/__init__.py +0 -0
  66. xfintech/data/source/baostock/session/tests/test_class_relay_all.py +694 -0
  67. xfintech/data/source/baostock/session/tests/test_class_session_all.py +505 -0
  68. xfintech/data/source/baostock/stock/__init__.py +0 -0
  69. xfintech/data/source/baostock/stock/hs300stock/__init__.py +3 -0
  70. xfintech/data/source/baostock/stock/hs300stock/constant.py +49 -0
  71. xfintech/data/source/baostock/stock/hs300stock/hs300stock.py +133 -0
  72. xfintech/data/source/baostock/stock/hs300stock/tests/__init__.py +1 -0
  73. xfintech/data/source/baostock/stock/hs300stock/tests/test_class_hs300index_all.py +413 -0
  74. xfintech/data/source/baostock/stock/minuteline/__init__.py +19 -0
  75. xfintech/data/source/baostock/stock/minuteline/constant.py +89 -0
  76. xfintech/data/source/baostock/stock/minuteline/minuteline.py +163 -0
  77. xfintech/data/source/baostock/stock/minuteline/tests/__init__.py +0 -0
  78. xfintech/data/source/baostock/stock/minuteline/tests/test_class_minuteline_all.py +582 -0
  79. xfintech/data/source/baostock/stock/stock/__init__.py +19 -0
  80. xfintech/data/source/baostock/stock/stock/constant.py +55 -0
  81. xfintech/data/source/baostock/stock/stock/stock.py +149 -0
  82. xfintech/data/source/baostock/stock/stock/tests/__init__.py +0 -0
  83. xfintech/data/source/baostock/stock/stock/tests/test_class_stock_all.py +508 -0
  84. xfintech/data/source/baostock/stock/stockinfo/__init__.py +5 -0
  85. xfintech/data/source/baostock/stock/stockinfo/constant.py +66 -0
  86. xfintech/data/source/baostock/stock/stockinfo/stockinfo.py +176 -0
  87. xfintech/data/source/baostock/stock/stockinfo/tests/__init__.py +1 -0
  88. xfintech/data/source/baostock/stock/stockinfo/tests/test_class_stockinfo_all.py +617 -0
  89. xfintech/data/source/baostock/stock/sz50stock/__init__.py +3 -0
  90. xfintech/data/source/baostock/stock/sz50stock/constant.py +49 -0
  91. xfintech/data/source/baostock/stock/sz50stock/sz50stock.py +133 -0
  92. xfintech/data/source/baostock/stock/sz50stock/tests/__init__.py +1 -0
  93. xfintech/data/source/baostock/stock/sz50stock/tests/test_class_sz50stock_all.py +397 -0
  94. xfintech/data/source/baostock/stock/tradedate/__init__.py +19 -0
  95. xfintech/data/source/baostock/stock/tradedate/constant.py +72 -0
  96. xfintech/data/source/baostock/stock/tradedate/tests/__init__.py +0 -0
  97. xfintech/data/source/baostock/stock/tradedate/tests/test_class_tradedate_all.py +695 -0
  98. xfintech/data/source/baostock/stock/tradedate/tradedate.py +208 -0
  99. xfintech/data/source/baostock/stock/zz500stock/__init__.py +3 -0
  100. xfintech/data/source/baostock/stock/zz500stock/constant.py +55 -0
  101. xfintech/data/source/baostock/stock/zz500stock/tests/__init__.py +1 -0
  102. xfintech/data/source/baostock/stock/zz500stock/tests/test_class_zz500stock_all.py +421 -0
  103. xfintech/data/source/baostock/stock/zz500stock/zz500stock.py +133 -0
  104. xfintech/data/source/tushare/__init__.py +61 -0
  105. xfintech/data/source/tushare/job/__init__.py +5 -0
  106. xfintech/data/source/tushare/job/job.py +257 -0
  107. xfintech/data/source/tushare/job/tests/test_class_tusharejob_all.py +589 -0
  108. xfintech/data/source/tushare/session/__init__.py +5 -0
  109. xfintech/data/source/tushare/session/relay.py +231 -0
  110. xfintech/data/source/tushare/session/session.py +239 -0
  111. xfintech/data/source/tushare/session/tests/test_class_relay_all.py +719 -0
  112. xfintech/data/source/tushare/session/tests/test_class_session_all.py +705 -0
  113. xfintech/data/source/tushare/stock/__init__.py +55 -0
  114. xfintech/data/source/tushare/stock/adjfactor/__init__.py +19 -0
  115. xfintech/data/source/tushare/stock/adjfactor/adjfactor.py +150 -0
  116. xfintech/data/source/tushare/stock/adjfactor/constant.py +71 -0
  117. xfintech/data/source/tushare/stock/adjfactor/tests/__init__.py +0 -0
  118. xfintech/data/source/tushare/stock/adjfactor/tests/test_class_adjfactor_all.py +372 -0
  119. xfintech/data/source/tushare/stock/capflow/__init__.py +19 -0
  120. xfintech/data/source/tushare/stock/capflow/capflow.py +171 -0
  121. xfintech/data/source/tushare/stock/capflow/constant.py +105 -0
  122. xfintech/data/source/tushare/stock/capflow/tests/__init__.py +0 -0
  123. xfintech/data/source/tushare/stock/capflow/tests/test_class_capflow_all.py +589 -0
  124. xfintech/data/source/tushare/stock/capflowdc/__init__.py +19 -0
  125. xfintech/data/source/tushare/stock/capflowdc/capflowdc.py +167 -0
  126. xfintech/data/source/tushare/stock/capflowdc/constant.py +95 -0
  127. xfintech/data/source/tushare/stock/capflowdc/tests/__init__.py +0 -0
  128. xfintech/data/source/tushare/stock/capflowdc/tests/test_class_capflowdc_all.py +814 -0
  129. xfintech/data/source/tushare/stock/capflowths/__init__.py +19 -0
  130. xfintech/data/source/tushare/stock/capflowths/capflowths.py +173 -0
  131. xfintech/data/source/tushare/stock/capflowths/constant.py +92 -0
  132. xfintech/data/source/tushare/stock/capflowths/tests/__init__.py +0 -0
  133. xfintech/data/source/tushare/stock/capflowths/tests/test_class_capflowths_all.py +551 -0
  134. xfintech/data/source/tushare/stock/company/__init__.py +19 -0
  135. xfintech/data/source/tushare/stock/company/company.py +188 -0
  136. xfintech/data/source/tushare/stock/company/constant.py +92 -0
  137. xfintech/data/source/tushare/stock/company/tests/__init__.py +1 -0
  138. xfintech/data/source/tushare/stock/company/tests/test_class_company_all.py +829 -0
  139. xfintech/data/source/tushare/stock/companybusiness/__init__.py +21 -0
  140. xfintech/data/source/tushare/stock/companybusiness/companybusiness.py +183 -0
  141. xfintech/data/source/tushare/stock/companybusiness/constant.py +91 -0
  142. xfintech/data/source/tushare/stock/companybusiness/tests/__init__.py +0 -0
  143. xfintech/data/source/tushare/stock/companybusiness/tests/test_class_companybusiness_all.py +633 -0
  144. xfintech/data/source/tushare/stock/companycashflow/__init__.py +21 -0
  145. xfintech/data/source/tushare/stock/companycashflow/companycashflow.py +277 -0
  146. xfintech/data/source/tushare/stock/companycashflow/constant.py +293 -0
  147. xfintech/data/source/tushare/stock/companycashflow/tests/__init__.py +0 -0
  148. xfintech/data/source/tushare/stock/companycashflow/tests/test_class_companycashflow_all.py +619 -0
  149. xfintech/data/source/tushare/stock/companydebt/__init__.py +19 -0
  150. xfintech/data/source/tushare/stock/companydebt/companydebt.py +339 -0
  151. xfintech/data/source/tushare/stock/companydebt/constant.py +403 -0
  152. xfintech/data/source/tushare/stock/companydebt/tests/__init__.py +0 -0
  153. xfintech/data/source/tushare/stock/companydebt/tests/test_class_companydebt_all.py +655 -0
  154. xfintech/data/source/tushare/stock/companyoverview/__init__.py +21 -0
  155. xfintech/data/source/tushare/stock/companyoverview/companyoverview.py +214 -0
  156. xfintech/data/source/tushare/stock/companyoverview/constant.py +152 -0
  157. xfintech/data/source/tushare/stock/companyoverview/tests/__init__.py +0 -0
  158. xfintech/data/source/tushare/stock/companyoverview/tests/test_class_companyoverview_all.py +647 -0
  159. xfintech/data/source/tushare/stock/companyprofit/__init__.py +21 -0
  160. xfintech/data/source/tushare/stock/companyprofit/companyprofit.py +272 -0
  161. xfintech/data/source/tushare/stock/companyprofit/constant.py +259 -0
  162. xfintech/data/source/tushare/stock/companyprofit/tests/__init__.py +0 -0
  163. xfintech/data/source/tushare/stock/companyprofit/tests/test_class_companyprofit_all.py +635 -0
  164. xfintech/data/source/tushare/stock/conceptcapflowdc/__init__.py +21 -0
  165. xfintech/data/source/tushare/stock/conceptcapflowdc/conceptcapflowdc.py +175 -0
  166. xfintech/data/source/tushare/stock/conceptcapflowdc/constant.py +106 -0
  167. xfintech/data/source/tushare/stock/conceptcapflowdc/tests/__init__.py +0 -0
  168. xfintech/data/source/tushare/stock/conceptcapflowdc/tests/test_class_conceptcapflowdc_all.py +568 -0
  169. xfintech/data/source/tushare/stock/conceptcapflowths/__init__.py +21 -0
  170. xfintech/data/source/tushare/stock/conceptcapflowths/conceptcapflowths.py +188 -0
  171. xfintech/data/source/tushare/stock/conceptcapflowths/constant.py +89 -0
  172. xfintech/data/source/tushare/stock/conceptcapflowths/tests/__init__.py +0 -0
  173. xfintech/data/source/tushare/stock/conceptcapflowths/tests/test_class_conceptcapflowths_all.py +516 -0
  174. xfintech/data/source/tushare/stock/dayline/__init__.py +19 -0
  175. xfintech/data/source/tushare/stock/dayline/constant.py +87 -0
  176. xfintech/data/source/tushare/stock/dayline/dayline.py +177 -0
  177. xfintech/data/source/tushare/stock/dayline/tests/__init__.py +0 -0
  178. xfintech/data/source/tushare/stock/dayline/tests/test_class_dayline_all.py +585 -0
  179. xfintech/data/source/tushare/stock/industrycapflowths/__init__.py +21 -0
  180. xfintech/data/source/tushare/stock/industrycapflowths/constant.py +89 -0
  181. xfintech/data/source/tushare/stock/industrycapflowths/industrycapflowths.py +192 -0
  182. xfintech/data/source/tushare/stock/industrycapflowths/tests/__init__.py +0 -0
  183. xfintech/data/source/tushare/stock/industrycapflowths/tests/test_class_industrycapflowths_all.py +683 -0
  184. xfintech/data/source/tushare/stock/marketindexcapflowdc/__init__.py +21 -0
  185. xfintech/data/source/tushare/stock/marketindexcapflowdc/constant.py +90 -0
  186. xfintech/data/source/tushare/stock/marketindexcapflowdc/marketindexcapflowdc.py +173 -0
  187. xfintech/data/source/tushare/stock/marketindexcapflowdc/tests/__init__.py +0 -0
  188. xfintech/data/source/tushare/stock/marketindexcapflowdc/tests/test_class_marketindexcapflowdc_all.py +793 -0
  189. xfintech/data/source/tushare/stock/monthline/__init__.py +19 -0
  190. xfintech/data/source/tushare/stock/monthline/constant.py +87 -0
  191. xfintech/data/source/tushare/stock/monthline/monthline.py +180 -0
  192. xfintech/data/source/tushare/stock/monthline/tests/__init__.py +0 -0
  193. xfintech/data/source/tushare/stock/monthline/tests/test_class_monthline_all.py +574 -0
  194. xfintech/data/source/tushare/stock/stock/__init__.py +19 -0
  195. xfintech/data/source/tushare/stock/stock/constant.py +105 -0
  196. xfintech/data/source/tushare/stock/stock/stock.py +193 -0
  197. xfintech/data/source/tushare/stock/stock/tests/__init__.py +0 -0
  198. xfintech/data/source/tushare/stock/stock/tests/test_class_stock_all.py +788 -0
  199. xfintech/data/source/tushare/stock/stockdividend/__init__.py +21 -0
  200. xfintech/data/source/tushare/stock/stockdividend/constant.py +111 -0
  201. xfintech/data/source/tushare/stock/stockdividend/stockdividend.py +180 -0
  202. xfintech/data/source/tushare/stock/stockdividend/tests/__init__.py +0 -0
  203. xfintech/data/source/tushare/stock/stockdividend/tests/test_class_stockdividend_all.py +725 -0
  204. xfintech/data/source/tushare/stock/stockinfo/__init__.py +19 -0
  205. xfintech/data/source/tushare/stock/stockinfo/constant.py +104 -0
  206. xfintech/data/source/tushare/stock/stockinfo/stockinfo.py +208 -0
  207. xfintech/data/source/tushare/stock/stockinfo/tests/__init__.py +0 -0
  208. xfintech/data/source/tushare/stock/stockinfo/tests/test_class_stockinfo_all.py +881 -0
  209. xfintech/data/source/tushare/stock/stockipo/__init__.py +19 -0
  210. xfintech/data/source/tushare/stock/stockipo/constant.py +90 -0
  211. xfintech/data/source/tushare/stock/stockipo/stockipo.py +234 -0
  212. xfintech/data/source/tushare/stock/stockipo/tests/__init__.py +1 -0
  213. xfintech/data/source/tushare/stock/stockipo/tests/test_class_stockipo_all.py +750 -0
  214. xfintech/data/source/tushare/stock/stockpledge/__init__.py +19 -0
  215. xfintech/data/source/tushare/stock/stockpledge/constant.py +72 -0
  216. xfintech/data/source/tushare/stock/stockpledge/stockpledge.py +158 -0
  217. xfintech/data/source/tushare/stock/stockpledge/tests/__init__.py +0 -0
  218. xfintech/data/source/tushare/stock/stockpledge/tests/test_class_stockpledge_all.py +664 -0
  219. xfintech/data/source/tushare/stock/stockpledgedetail/__init__.py +21 -0
  220. xfintech/data/source/tushare/stock/stockpledgedetail/constant.py +85 -0
  221. xfintech/data/source/tushare/stock/stockpledgedetail/stockpledgedetail.py +171 -0
  222. xfintech/data/source/tushare/stock/stockpledgedetail/tests/__init__.py +0 -0
  223. xfintech/data/source/tushare/stock/stockpledgedetail/tests/test_class_stockpledgedetail_all.py +112 -0
  224. xfintech/data/source/tushare/stock/stockst/__init__.py +19 -0
  225. xfintech/data/source/tushare/stock/stockst/constant.py +80 -0
  226. xfintech/data/source/tushare/stock/stockst/stockst.py +189 -0
  227. xfintech/data/source/tushare/stock/stockst/tests/__init__.py +0 -0
  228. xfintech/data/source/tushare/stock/stockst/tests/test_class_stockst_all.py +693 -0
  229. xfintech/data/source/tushare/stock/stocksuspend/__init__.py +21 -0
  230. xfintech/data/source/tushare/stock/stocksuspend/constant.py +75 -0
  231. xfintech/data/source/tushare/stock/stocksuspend/stocksuspend.py +151 -0
  232. xfintech/data/source/tushare/stock/stocksuspend/tests/__init__.py +0 -0
  233. xfintech/data/source/tushare/stock/stocksuspend/tests/test_class_stocksuspend_all.py +626 -0
  234. xfintech/data/source/tushare/stock/techindex/__init__.py +19 -0
  235. xfintech/data/source/tushare/stock/techindex/constant.py +600 -0
  236. xfintech/data/source/tushare/stock/techindex/techindex.py +314 -0
  237. xfintech/data/source/tushare/stock/techindex/tests/__init__.py +0 -0
  238. xfintech/data/source/tushare/stock/techindex/tests/test_class_techindex_all.py +576 -0
  239. xfintech/data/source/tushare/stock/tradedate/__init__.py +19 -0
  240. xfintech/data/source/tushare/stock/tradedate/constant.py +93 -0
  241. xfintech/data/source/tushare/stock/tradedate/tests/__init__.py +0 -0
  242. xfintech/data/source/tushare/stock/tradedate/tests/test_class_tradedate_all.py +947 -0
  243. xfintech/data/source/tushare/stock/tradedate/tradedate.py +234 -0
  244. xfintech/data/source/tushare/stock/weekline/__init__.py +19 -0
  245. xfintech/data/source/tushare/stock/weekline/constant.py +87 -0
  246. xfintech/data/source/tushare/stock/weekline/tests/__init__.py +0 -0
  247. xfintech/data/source/tushare/stock/weekline/tests/test_class_weekline_all.py +575 -0
  248. xfintech/data/source/tushare/stock/weekline/weekline.py +182 -0
  249. xfintech/fabric/__init__.py +18 -0
  250. xfintech/fabric/column/__init__.py +7 -0
  251. xfintech/fabric/column/info.py +202 -0
  252. xfintech/fabric/column/kind.py +102 -0
  253. xfintech/fabric/column/tests/__init__.py +0 -0
  254. xfintech/fabric/column/tests/test_class_info_all.py +207 -0
  255. xfintech/fabric/column/tests/test_class_kind_all.py +80 -0
  256. xfintech/fabric/table/__init__.py +5 -0
  257. xfintech/fabric/table/info.py +263 -0
  258. xfintech/fabric/table/tests/__init__.py +0 -0
  259. xfintech/fabric/table/tests/test_class_info_all.py +547 -0
  260. xfintech/serde/__init__.py +35 -0
  261. xfintech/serde/common/__init__.py +9 -0
  262. xfintech/serde/common/dataformat.py +78 -0
  263. xfintech/serde/common/deserialiserlike.py +38 -0
  264. xfintech/serde/common/error.py +182 -0
  265. xfintech/serde/common/serialiserlike.py +38 -0
  266. xfintech/serde/common/tests/__init__.py +1 -0
  267. xfintech/serde/common/tests/test_class_dataformat_all.py +694 -0
  268. xfintech/serde/common/tests/test_class_deserialiserlike_all.py +500 -0
  269. xfintech/serde/common/tests/test_class_errors_all.py +518 -0
  270. xfintech/serde/common/tests/test_class_serialiserlike_all.py +401 -0
  271. xfintech/serde/deserialiser/__init__.py +7 -0
  272. xfintech/serde/deserialiser/pandas.py +113 -0
  273. xfintech/serde/deserialiser/python.py +68 -0
  274. xfintech/serde/deserialiser/tests/__init__.py +1 -0
  275. xfintech/serde/deserialiser/tests/test_class_pandasdeserialiser_all.py +503 -0
  276. xfintech/serde/deserialiser/tests/test_class_pythondeserialiser_all.py +570 -0
  277. xfintech/serde/serialiser/__init__.py +7 -0
  278. xfintech/serde/serialiser/pandas.py +116 -0
  279. xfintech/serde/serialiser/python.py +71 -0
  280. xfintech/serde/serialiser/tests/__init__.py +1 -0
  281. xfintech/serde/serialiser/tests/test_class_pandasserialiser_all.py +474 -0
  282. xfintech/serde/serialiser/tests/test_class_pythonserialiser_all.py +508 -0
@@ -0,0 +1,505 @@
1
+ """
2
+ Test suite for Session class
3
+ Tests cover initialization, connection modes, state management, and session lifecycle
4
+ """
5
+
6
+ from datetime import datetime
7
+ from unittest.mock import Mock, patch
8
+
9
+ import pandas as pd
10
+ import pytest
11
+
12
+ from xfintech.data.source.baostock.session.session import Session
13
+
14
+ # ============================================================================
15
+ # Session Initialization Tests - Direct Mode
16
+ # ============================================================================
17
+
18
+
19
+ @patch("xfintech.data.source.baostock.session.session.bs")
20
+ def test_session_init_direct_mode_basic(mock_bs):
21
+ """Test Session initialization in direct mode"""
22
+ mock_bs.login.return_value = Mock()
23
+
24
+ session = Session(mode="direct")
25
+
26
+ assert session.mode == "direct"
27
+ assert session._credential is None
28
+ assert session.relay_url is None
29
+ assert session.relay_secret is None
30
+ assert len(session.id) == 8
31
+ assert session.connected is True
32
+
33
+
34
+ @patch("xfintech.data.source.baostock.session.session.bs")
35
+ def test_session_init_direct_mode_default(mock_bs):
36
+ """Test Session defaults to direct mode"""
37
+ mock_bs.login.return_value = Mock()
38
+
39
+ session = Session()
40
+
41
+ assert session.mode == "direct"
42
+
43
+
44
+ @patch("xfintech.data.source.baostock.session.session.bs")
45
+ def test_session_init_direct_mode_uppercase(mock_bs):
46
+ """Test Session handles uppercase mode"""
47
+ mock_bs.login.return_value = Mock()
48
+
49
+ session = Session(mode="DIRECT")
50
+
51
+ assert session.mode == "direct"
52
+
53
+
54
+ @patch("xfintech.data.source.baostock.session.session.bs")
55
+ def test_session_init_direct_calls_login(mock_bs):
56
+ """Test Session calls bs.login in direct mode"""
57
+ mock_bs.login.return_value = Mock()
58
+
59
+ Session(mode="direct")
60
+
61
+ mock_bs.login.assert_called_once()
62
+
63
+
64
+ @patch("xfintech.data.source.baostock.session.session.bs")
65
+ def test_session_init_direct_creates_connection(mock_bs):
66
+ """Test Session creates baostock connection"""
67
+ mock_bs.login.return_value = Mock()
68
+
69
+ session = Session(mode="direct")
70
+
71
+ assert session.connection is mock_bs
72
+
73
+
74
+ # ============================================================================
75
+ # Session Resolve Methods Tests
76
+ # ============================================================================
77
+
78
+
79
+ def test_session_resolve_mode_invalid():
80
+ """Test _resolve_mode raises error with invalid mode"""
81
+ with pytest.raises(ValueError, match="Unsupported mode"):
82
+ Session(mode="invalid")
83
+
84
+
85
+ @patch("xfintech.data.source.baostock.session.session.bs")
86
+ def test_session_resolve_mode_empty_returns_direct(mock_bs):
87
+ """Test _resolve_mode returns 'direct' for empty string"""
88
+ mock_bs.login.return_value = Mock()
89
+
90
+ session = Session(mode="")
91
+
92
+ assert session.mode == "direct"
93
+
94
+
95
+ # ============================================================================
96
+ # Session ID Tests
97
+ # ============================================================================
98
+
99
+
100
+ @patch("xfintech.data.source.baostock.session.session.bs")
101
+ def test_session_id_length(mock_bs):
102
+ """Test Session ID is 8 characters"""
103
+ mock_bs.login.return_value = Mock()
104
+
105
+ session = Session()
106
+
107
+ assert len(session.id) == 8
108
+
109
+
110
+ @patch("xfintech.data.source.baostock.session.session.bs")
111
+ def test_session_id_unique(mock_bs):
112
+ """Test different Sessions have different IDs"""
113
+ mock_bs.login.return_value = Mock()
114
+
115
+ session1 = Session()
116
+ session2 = Session()
117
+
118
+ assert session1.id != session2.id
119
+
120
+
121
+ # ============================================================================
122
+ # Session Properties Tests
123
+ # ============================================================================
124
+
125
+
126
+ @patch("xfintech.data.source.baostock.session.session.bs")
127
+ def test_session_connected_property_true(mock_bs):
128
+ """Test connected property returns True when connection exists"""
129
+ mock_bs.login.return_value = Mock()
130
+
131
+ session = Session()
132
+
133
+ assert session.connected is True
134
+
135
+
136
+ @patch("xfintech.data.source.baostock.session.session.bs")
137
+ def test_session_connected_property_false(mock_bs):
138
+ """Test connected property returns False when no connection"""
139
+ mock_bs.login.return_value = Mock()
140
+
141
+ session = Session()
142
+ session.connection = None
143
+
144
+ assert session.connected is False
145
+
146
+
147
+ @patch("xfintech.data.source.baostock.session.session.bs")
148
+ @patch("xfintech.data.source.baostock.session.session.pd.Timestamp")
149
+ def test_session_duration_property_no_start(mock_timestamp, mock_bs):
150
+ """Test duration returns 0.0 when not started"""
151
+ mock_bs.login.return_value = Mock()
152
+
153
+ session = Session()
154
+ session.start_at = None
155
+
156
+ assert session.duration == 0.0
157
+
158
+
159
+ @patch("xfintech.data.source.baostock.session.session.bs")
160
+ def test_session_duration_property_ongoing(mock_bs):
161
+ """Test duration calculates correctly for ongoing session"""
162
+ mock_bs.login.return_value = Mock()
163
+
164
+ # Create session
165
+ session = Session()
166
+
167
+ # Set times directly
168
+ session.start_at = pd.Timestamp("2024-01-15 10:00:00")
169
+ session.finish_at = None
170
+
171
+ # Mock datetime.now to return a specific time
172
+ with patch(
173
+ "xfintech.data.source.baostock.session.session.datetime",
174
+ ) as mock_datetime:
175
+ mock_now = datetime(2024, 1, 15, 10, 0, 10)
176
+ mock_datetime.now.return_value = mock_now
177
+
178
+ duration = session.duration
179
+
180
+ assert duration == 10.0
181
+
182
+
183
+ @patch("xfintech.data.source.baostock.session.session.bs")
184
+ def test_session_duration_property_finished(mock_bs):
185
+ """Test duration calculates correctly for finished session"""
186
+ mock_bs.login.return_value = Mock()
187
+
188
+ session = Session()
189
+ session.start_at = pd.Timestamp("2024-01-15 10:00:00")
190
+ session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
191
+
192
+ assert session.duration == 30.0
193
+
194
+
195
+ # ============================================================================
196
+ # Session String Representation Tests
197
+ # ============================================================================
198
+
199
+
200
+ @patch("xfintech.data.source.baostock.session.session.bs")
201
+ def test_session_str(mock_bs):
202
+ """Test __str__ returns session ID"""
203
+ mock_bs.login.return_value = Mock()
204
+
205
+ session = Session()
206
+
207
+ assert str(session) == session.id
208
+
209
+
210
+ @patch("xfintech.data.source.baostock.session.session.bs")
211
+ def test_session_repr(mock_bs):
212
+ """Test __repr__ includes class name, connected status, and mode"""
213
+ mock_bs.login.return_value = Mock()
214
+
215
+ session = Session(mode="direct")
216
+
217
+ result = repr(session)
218
+ assert "Session" in result
219
+ assert "connected=True" in result
220
+ assert "mode=direct" in result
221
+
222
+
223
+ @patch("xfintech.data.source.baostock.session.session.BaostockRelayClient")
224
+ def test_session_repr_relay_mode(mock_relay_client_class):
225
+ """Test __repr__ shows relay mode"""
226
+ mock_client = Mock()
227
+ mock_client.check_health.return_value = True
228
+ mock_relay_client_class.return_value = mock_client
229
+
230
+ session = Session(
231
+ mode="relay",
232
+ relay_url="https://relay.example.com",
233
+ relay_secret="relay-secret",
234
+ )
235
+
236
+ result = repr(session)
237
+ assert "mode=relay" in result
238
+
239
+
240
+ # ============================================================================
241
+ # Session Start/End Methods Tests
242
+ # ============================================================================
243
+
244
+
245
+ @patch("xfintech.data.source.baostock.session.session.bs")
246
+ @patch("xfintech.data.source.baostock.session.session.pd.Timestamp")
247
+ def test_session_start_method(mock_timestamp, mock_bs):
248
+ """Test start method sets start_at"""
249
+ mock_bs.login.return_value = Mock()
250
+ mock_now = pd.Timestamp("2024-01-15 10:00:00")
251
+ mock_timestamp.now.return_value = mock_now
252
+
253
+ session = Session()
254
+ session.start_at = None
255
+ session.start()
256
+
257
+ assert session.start_at == mock_now
258
+
259
+
260
+ @patch("xfintech.data.source.baostock.session.session.bs")
261
+ @patch("xfintech.data.source.baostock.session.session.pd.Timestamp")
262
+ def test_session_end_method(mock_timestamp, mock_bs):
263
+ """Test end method sets finish_at"""
264
+ mock_bs.login.return_value = Mock()
265
+ mock_now = pd.Timestamp("2024-01-15 10:00:30")
266
+ mock_timestamp.now.return_value = mock_now
267
+
268
+ session = Session()
269
+ session.end()
270
+
271
+ assert session.finish_at == mock_now
272
+
273
+
274
+ @patch("xfintech.data.source.baostock.session.session.bs")
275
+ def test_session_get_start_iso_none(mock_bs):
276
+ """Test get_start_iso returns None when start_at is None"""
277
+ mock_bs.login.return_value = Mock()
278
+
279
+ session = Session()
280
+ session.start_at = None
281
+
282
+ assert session.get_start_iso() is None
283
+
284
+
285
+ @patch("xfintech.data.source.baostock.session.session.bs")
286
+ def test_session_get_start_iso_with_value(mock_bs):
287
+ """Test get_start_iso returns ISO format"""
288
+ mock_bs.login.return_value = Mock()
289
+
290
+ session = Session()
291
+ session.start_at = pd.Timestamp("2024-01-15 10:00:00")
292
+
293
+ result = session.get_start_iso()
294
+ assert "2024-01-15" in result
295
+
296
+
297
+ @patch("xfintech.data.source.baostock.session.session.bs")
298
+ def test_session_get_finish_iso_none(mock_bs):
299
+ """Test get_finish_iso returns None when finish_at is None"""
300
+ mock_bs.login.return_value = Mock()
301
+
302
+ session = Session()
303
+ session.finish_at = None
304
+
305
+ assert session.get_finish_iso() is None
306
+
307
+
308
+ @patch("xfintech.data.source.baostock.session.session.bs")
309
+ def test_session_get_finish_iso_with_value(mock_bs):
310
+ """Test get_finish_iso returns ISO format"""
311
+ mock_bs.login.return_value = Mock()
312
+
313
+ session = Session()
314
+ session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
315
+ session = Session()
316
+ session.connection = None
317
+
318
+ result = session.connect()
319
+
320
+ assert result is not None
321
+
322
+
323
+ @patch("xfintech.data.source.baostock.session.session.bs")
324
+ def test_session_connect_already_connected(mock_bs):
325
+ """Test connect returns existing connection if already connected"""
326
+ mock_bs.login.return_value = Mock()
327
+
328
+ session = Session()
329
+ first_connection = session.connection
330
+
331
+ # Reset call count
332
+ mock_bs.login.reset_mock()
333
+
334
+ # Try to connect again
335
+ result = session.connect()
336
+
337
+ assert result is first_connection
338
+ # Should not call login again
339
+ mock_bs.login.assert_not_called()
340
+
341
+
342
+ @patch("xfintech.data.source.baostock.session.session.bs")
343
+ @patch("xfintech.data.source.baostock.session.session.pd.Timestamp")
344
+ def test_session_disconnect_clears_connection(mock_timestamp, mock_bs):
345
+ """Test disconnect clears connection"""
346
+ mock_bs.login.return_value = Mock()
347
+ mock_bs.logout.return_value = Mock()
348
+
349
+ session = Session()
350
+ assert session.connected is True
351
+
352
+ session.disconnect()
353
+
354
+ assert session.connection is None
355
+ assert session.connected is False
356
+ mock_bs.logout.assert_called_once()
357
+
358
+
359
+ @patch("xfintech.data.source.baostock.session.session.bs")
360
+ @patch("xfintech.data.source.baostock.session.session.pd.Timestamp")
361
+ def test_session_disconnect_sets_finish_time(mock_timestamp, mock_bs):
362
+ """Test disconnect sets finish_at"""
363
+ mock_bs.login.return_value = Mock()
364
+ mock_bs.logout.return_value = Mock()
365
+ mock_now = pd.Timestamp("2024-01-15 10:00:30")
366
+ mock_timestamp.now.return_value = mock_now
367
+
368
+ session = Session()
369
+ session.disconnect()
370
+
371
+ assert session.finish_at == mock_now
372
+
373
+
374
+ # ============================================================================
375
+ # Session Describe Method Tests
376
+ # ============================================================================
377
+
378
+
379
+ @patch("xfintech.data.source.baostock.session.session.bs")
380
+ def test_session_describe_basic(mock_bs):
381
+ """Test describe returns basic session info"""
382
+ mock_bs.login.return_value = Mock()
383
+
384
+ session = Session(mode="direct")
385
+ result = session.describe()
386
+
387
+ assert "id" in result
388
+ assert result["id"] == session.id
389
+ assert "mode" in result
390
+ assert result["mode"] == "direct"
391
+ assert "connected" in result
392
+ assert result["connected"] is True
393
+
394
+
395
+ @patch("xfintech.data.source.baostock.session.session.BaostockRelayClient")
396
+ def test_session_describe_relay_mode(mock_relay_client_class):
397
+ """Test describe includes relay info in relay mode"""
398
+ mock_client = Mock()
399
+ mock_client.check_health.return_value = True
400
+
401
+
402
+ @patch("xfintech.data.source.baostock.session.session.bs")
403
+ def test_session_describe_with_timestamps(mock_bs):
404
+ """Test describe includes timestamps when available"""
405
+ mock_bs.login.return_value = Mock()
406
+
407
+ session = Session()
408
+ session.start_at = pd.Timestamp("2024-01-15 10:00:00")
409
+ session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
410
+
411
+ result = session.describe()
412
+
413
+ assert "start_at" in result
414
+ assert "finish_at" in result
415
+
416
+
417
+ @patch("xfintech.data.source.baostock.session.session.bs")
418
+ def test_session_describe_without_finish(mock_bs):
419
+ """Test describe handles ongoing session"""
420
+ mock_bs.login.return_value = Mock()
421
+
422
+ session = Session()
423
+ session.finish_at = None
424
+
425
+ result = session.describe()
426
+
427
+ assert "start_at" in result
428
+ assert "finish_at" not in result
429
+
430
+
431
+ # ============================================================================
432
+ # Session To Dict Method Tests
433
+ # ============================================================================
434
+
435
+
436
+ @patch("xfintech.data.source.baostock.session.session.bs")
437
+ def test_session_to_dict_structure(mock_bs):
438
+ """Test to_dict returns expected structure"""
439
+ mock_bs.login.return_value = Mock()
440
+
441
+ session = Session(mode="direct")
442
+ result = session.to_dict()
443
+
444
+ assert "id" in result
445
+ assert "connected" in result
446
+ assert "mode" in result
447
+ assert "relay" in result
448
+ assert "start_at" in result
449
+ assert "finish_at" in result
450
+ assert "duration" in result
451
+
452
+
453
+ @patch("xfintech.data.source.baostock.session.session.bs")
454
+ def test_session_to_dict_includes_duration(mock_bs):
455
+ """Test to_dict includes duration"""
456
+ mock_bs.login.return_value = Mock()
457
+
458
+ session = Session()
459
+ session.start_at = pd.Timestamp("2024-01-15 10:00:00")
460
+ session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
461
+
462
+ result = session.to_dict()
463
+
464
+ assert result["duration"] == 30.0
465
+
466
+
467
+ # ============================================================================
468
+ # Integration Tests
469
+ # ============================================================================
470
+
471
+
472
+ @patch("xfintech.data.source.baostock.session.session.bs")
473
+ def test_session_full_lifecycle_direct(mock_bs):
474
+ """Test complete session lifecycle in direct mode"""
475
+ mock_bs.login.return_value = Mock()
476
+ mock_bs.logout.return_value = Mock()
477
+
478
+ # Create session
479
+ session = Session(mode="direct")
480
+ assert session.connected is True
481
+
482
+ # Use connection
483
+ assert session.connection is mock_bs
484
+
485
+ # Disconnect
486
+ session.disconnect()
487
+ assert session.connected is False
488
+ assert session.finish_at is not None
489
+ mock_bs.logout.assert_called_once()
490
+
491
+
492
+ @patch("xfintech.data.source.baostock.session.session.bs")
493
+ def test_session_reconnect(mock_bs):
494
+ """Test reconnecting after disconnect"""
495
+ mock_bs.login.return_value = Mock()
496
+ mock_bs.logout.return_value = Mock()
497
+
498
+ session = Session()
499
+ session.disconnect()
500
+
501
+ # Reconnect
502
+ session.connect()
503
+
504
+ assert session.connected is True
505
+ assert session.connection is not None
File without changes
@@ -0,0 +1,3 @@
1
+ from .hs300stock import HS300Stock
2
+
3
+ __all__ = ["HS300Stock"]
@@ -0,0 +1,49 @@
1
+ from __future__ import annotations
2
+
3
+ from xfintech.data.common.paginate import Paginate
4
+ from xfintech.fabric.column.info import ColumnInfo
5
+ from xfintech.fabric.column.kind import ColumnKind
6
+ from xfintech.fabric.table.info import TableInfo
7
+
8
+ PROVIDER = "baostock"
9
+ SOURCE_NAME = "query_hs300_stocks"
10
+ URL = "http://www.baostock.com/mainContent?file=hs300Stock.md"
11
+ ARGS = {}
12
+
13
+ # Exported constants
14
+ NAME = "hs300stock"
15
+ KEY = "/baostock/hs300stock"
16
+ PAGINATE = Paginate(
17
+ pagesize=10000,
18
+ pagelimit=100,
19
+ )
20
+ SOURCE = TableInfo(
21
+ desc="沪深300成分股(BaoStock格式)",
22
+ meta={
23
+ "provider": PROVIDER,
24
+ "source": SOURCE_NAME,
25
+ "url": URL,
26
+ "args": ARGS,
27
+ "type": "static",
28
+ "scale": "crosssection",
29
+ },
30
+ columns=[
31
+ ColumnInfo(name="updateDate", kind=ColumnKind.STRING, desc="更新日期"),
32
+ ColumnInfo(name="code", kind=ColumnKind.STRING, desc="证券代码"),
33
+ ColumnInfo(name="code_name", kind=ColumnKind.STRING, desc="证券名称"),
34
+ ],
35
+ )
36
+ TARGET = TableInfo(
37
+ desc="沪深300成分股(xfintech格式)",
38
+ meta={
39
+ "key": KEY,
40
+ "name": NAME,
41
+ "type": "static",
42
+ "scale": "crosssection",
43
+ },
44
+ columns=[
45
+ ColumnInfo(name="update_date", kind=ColumnKind.STRING, desc="更新日期"),
46
+ ColumnInfo(name="code", kind=ColumnKind.STRING, desc="证券代码"),
47
+ ColumnInfo(name="name", kind=ColumnKind.STRING, desc="证券名称"),
48
+ ],
49
+ )
@@ -0,0 +1,133 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Dict, List, Optional
4
+
5
+ import pandas as pd
6
+
7
+ from xfintech.data.common.cache import Cache
8
+ from xfintech.data.common.coolant import Coolant
9
+ from xfintech.data.common.params import Params
10
+ from xfintech.data.common.retry import Retry
11
+ from xfintech.data.job import JobHouse
12
+ from xfintech.data.source.baostock.job import BaostockJob
13
+ from xfintech.data.source.baostock.session.session import Session
14
+ from xfintech.data.source.baostock.stock.hs300stock.constant import (
15
+ KEY,
16
+ NAME,
17
+ PAGINATE,
18
+ SOURCE,
19
+ TARGET,
20
+ )
21
+
22
+
23
+ @JobHouse.register(KEY, alias=KEY)
24
+ class HS300Stock(BaostockJob):
25
+ """
26
+ 描述:
27
+ - 获取沪深300成分股
28
+ - 返回沪深300指数的300只成份股信息
29
+ - 每周一更新
30
+ - API文档: http://www.baostock.com/mainContent?file=hs300Stock.md
31
+ - SCALE: CrossSection
32
+ - TYPE: Static
33
+ - PAGINATE: 10000 rows / 100 pages
34
+
35
+ 属性:
36
+ - name: str, 作业名称 'hs300index'。
37
+ - key: str, 作业键 '/baostock/hs300index'。
38
+ - session: Session, Baostock会话对象。
39
+ - source: TableInfo, 源表信息(BaoStock原始格式)。
40
+ - target: TableInfo, 目标表信息(xfintech格式)。
41
+ - params: Params, 查询参数(此API无需参数)。
42
+ - coolant: Coolant, 请求冷却控制。
43
+ - paginate: Paginate, 分页控制(pagesize=10000, pagelimit=100)。
44
+ - retry: Retry, 重试策略。
45
+ - cache: Cache, 缓存管理。
46
+
47
+ 方法:
48
+ - run(): 执行作业,返回沪深300成分股DataFrame。
49
+ - _run(): 内部执行逻辑,处理参数并调用API。
50
+ - transform(data): 转换数据格式,将源格式转为目标格式。
51
+ - list_codes(): 返回所有股票代码列表。
52
+ - list_names(): 返回所有股票名称列表。
53
+
54
+ 例子:
55
+ ```python
56
+ from xfintech.data.source.baostock.session import Session
57
+ from xfintech.data.source.baostock.stock.hs300index import HS300Stock
58
+
59
+ session = Session()
60
+
61
+ # 获取沪深300成分股
62
+ job = HS300Stock(session=session)
63
+ df = job.run()
64
+
65
+ # 获取代码列表
66
+ codes = job.list_codes()
67
+ ```
68
+ """
69
+
70
+ def __init__(
71
+ self,
72
+ session: Session,
73
+ params: Optional[Params | Dict[str, Any]] = None,
74
+ coolant: Optional[Coolant | Dict[str, Any]] = None,
75
+ retry: Optional[Retry | Dict[str, Any]] = None,
76
+ cache: Optional[Cache | Dict[str, str] | bool] = None,
77
+ ) -> None:
78
+ super().__init__(
79
+ name=NAME,
80
+ key=KEY,
81
+ session=session,
82
+ source=SOURCE,
83
+ target=TARGET,
84
+ params=params,
85
+ coolant=coolant,
86
+ paginate=PAGINATE,
87
+ retry=retry,
88
+ cache=cache,
89
+ )
90
+
91
+ def _run(self) -> pd.DataFrame:
92
+ cached = self._load_cache()
93
+ if cached is not None:
94
+ return cached
95
+
96
+ payload = self.params.to_dict()
97
+ payload = self._parse_date_params(payload, keys=["date"])
98
+ # Fetch data from API
99
+ data = self._fetchall(
100
+ api=self.connection.query_hs300_stocks,
101
+ **payload,
102
+ )
103
+ result = self.transform(data)
104
+ self._save_cache(result)
105
+ return result
106
+
107
+ def transform(
108
+ self,
109
+ data: pd.DataFrame,
110
+ ) -> pd.DataFrame:
111
+ cols = self.target.list_column_names()
112
+ if data is None or data.empty:
113
+ return pd.DataFrame(columns=cols)
114
+
115
+ out = data.copy()
116
+ out["update_date"] = out["updateDate"].astype(str)
117
+ out["code"] = out["code"].astype(str)
118
+ out["name"] = out["code_name"].astype(str)
119
+
120
+ # Finalize output
121
+ out = out[cols].drop_duplicates()
122
+ out = out.sort_values(by=["code"])
123
+ out = out.reset_index(drop=True)
124
+ self.markpoint("transform[OK]")
125
+ return out
126
+
127
+ def list_codes(self) -> List[str]:
128
+ df = self.run()
129
+ return sorted(df["code"].unique().tolist())
130
+
131
+ def list_names(self) -> List[str]:
132
+ df = self.run()
133
+ return sorted(df["name"].unique().tolist())
@@ -0,0 +1 @@
1
+ """Tests for hs300index module."""