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,705 @@
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.tushare.session.relay import RelayConnection
13
+ from xfintech.data.source.tushare.session.session import Session
14
+
15
+ # ============================================================================
16
+ # Session Initialization Tests - Direct Mode
17
+ # ============================================================================
18
+
19
+
20
+ @patch("xfintech.data.source.tushare.session.session.ts")
21
+ def test_session_init_direct_mode_basic(mock_ts):
22
+ """Test Session initialization in direct mode"""
23
+ mock_ts.pro_api.return_value = Mock()
24
+
25
+ session = Session(credential="test-token", mode="direct")
26
+
27
+ assert session.mode == "direct"
28
+ assert session._credential == "test-token"
29
+ assert session.relay_url is None
30
+ assert session.relay_secret is None
31
+ assert len(session.id) == 8
32
+ assert session.connected is True
33
+
34
+
35
+ @patch("xfintech.data.source.tushare.session.session.ts")
36
+ def test_session_init_direct_mode_default(mock_ts):
37
+ """Test Session defaults to direct mode"""
38
+ mock_ts.pro_api.return_value = Mock()
39
+
40
+ session = Session(credential="test-token")
41
+
42
+ assert session.mode == "direct"
43
+
44
+
45
+ @patch("xfintech.data.source.tushare.session.session.ts")
46
+ def test_session_init_direct_mode_uppercase(mock_ts):
47
+ """Test Session handles uppercase mode"""
48
+ mock_ts.pro_api.return_value = Mock()
49
+
50
+ session = Session(credential="test-token", mode="DIRECT")
51
+
52
+ assert session.mode == "direct"
53
+
54
+
55
+ @patch("xfintech.data.source.tushare.session.session.ts")
56
+ def test_session_init_direct_sets_token(mock_ts):
57
+ """Test Session sets tushare token in direct mode"""
58
+ mock_ts.pro_api.return_value = Mock()
59
+
60
+ Session(credential="test-token", mode="direct")
61
+
62
+ mock_ts.set_token.assert_called_once_with("test-token")
63
+
64
+
65
+ @patch("xfintech.data.source.tushare.session.session.ts")
66
+ def test_session_init_direct_creates_connection(mock_ts):
67
+ """Test Session creates pro_api connection"""
68
+ mock_api = Mock()
69
+ mock_ts.pro_api.return_value = mock_api
70
+
71
+ session = Session(credential="test-token", mode="direct")
72
+
73
+ assert session.connection is mock_api
74
+ mock_ts.pro_api.assert_called_once()
75
+
76
+
77
+ # ============================================================================
78
+ # Session Initialization Tests - Relay Mode
79
+ # ============================================================================
80
+
81
+
82
+ @patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
83
+ def test_session_init_relay_mode_basic(mock_relay_client_class):
84
+ """Test Session initialization in relay mode"""
85
+ mock_client = Mock()
86
+ mock_client.check_health.return_value = True
87
+ mock_relay_client_class.return_value = mock_client
88
+
89
+ session = Session(
90
+ credential="test-token",
91
+ mode="relay",
92
+ relay_url="https://relay.example.com",
93
+ relay_secret="relay-secret",
94
+ )
95
+
96
+ assert session.mode == "relay"
97
+ assert session.relay_url == "https://relay.example.com"
98
+ assert session.relay_secret == "relay-secret"
99
+ assert session.connected is True
100
+
101
+
102
+ @patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
103
+ def test_session_init_relay_mode_creates_client(mock_relay_client_class):
104
+ """Test Session creates RelayClient in relay mode"""
105
+ mock_client = Mock()
106
+ mock_client.check_health.return_value = True
107
+ mock_relay_client_class.return_value = mock_client
108
+
109
+ Session(
110
+ credential="test-token",
111
+ mode="relay",
112
+ relay_url="https://relay.example.com",
113
+ relay_secret="relay-secret",
114
+ )
115
+
116
+ mock_relay_client_class.assert_called_once_with(
117
+ url="https://relay.example.com",
118
+ secret="relay-secret",
119
+ )
120
+
121
+
122
+ @patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
123
+ def test_session_init_relay_mode_checks_health(mock_relay_client_class):
124
+ """Test Session checks health in relay mode"""
125
+ mock_client = Mock()
126
+ mock_relay_client_class.return_value = mock_client
127
+
128
+ Session(
129
+ credential="test-token",
130
+ mode="relay",
131
+ relay_url="https://relay.example.com",
132
+ relay_secret="relay-secret",
133
+ )
134
+
135
+ mock_client.check_health.assert_called_once()
136
+
137
+
138
+ @patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
139
+ def test_session_init_relay_mode_connection_type(mock_relay_client_class):
140
+ """Test Session connection is RelayConnection in relay mode"""
141
+ mock_client = Mock()
142
+ mock_client.check_health.return_value = True
143
+ mock_relay_client_class.return_value = mock_client
144
+
145
+ session = Session(
146
+ credential="test-token",
147
+ mode="relay",
148
+ relay_url="https://relay.example.com",
149
+ relay_secret="relay-secret",
150
+ )
151
+
152
+ assert isinstance(session.connection, RelayConnection)
153
+
154
+
155
+ def test_session_init_relay_mode_missing_url():
156
+ """Test Session raises error when relay_url is missing in relay mode"""
157
+ with pytest.raises(ValueError, match="URL must be provided in relay mode"):
158
+ Session(
159
+ credential="test-token",
160
+ mode="relay",
161
+ relay_secret="relay-secret",
162
+ )
163
+
164
+
165
+ def test_session_init_relay_mode_missing_secret():
166
+ """Test Session raises error when relay_secret is missing in relay mode"""
167
+ with pytest.raises(ValueError, match="Secret must be provided in relay mode"):
168
+ Session(
169
+ credential="test-token",
170
+ mode="relay",
171
+ relay_url="https://relay.example.com",
172
+ )
173
+
174
+
175
+ # ============================================================================
176
+ # Session Resolve Methods Tests
177
+ # ============================================================================
178
+
179
+
180
+ def test_session_resolve_mode_invalid():
181
+ """Test _resolve_mode raises error with invalid mode"""
182
+ with pytest.raises(ValueError, match="Unsupported mode"):
183
+ Session(credential="test-token", mode="invalid")
184
+
185
+
186
+ @patch("xfintech.data.source.tushare.session.session.ts")
187
+ def test_session_resolve_mode_empty_returns_direct(mock_ts):
188
+ """Test _resolve_mode returns 'direct' for empty string"""
189
+ mock_ts.pro_api.return_value = Mock()
190
+
191
+ session = Session(credential="test-token", mode="")
192
+
193
+ assert session.mode == "direct"
194
+
195
+
196
+ # ============================================================================
197
+ # Session ID Tests
198
+ # ============================================================================
199
+
200
+
201
+ @patch("xfintech.data.source.tushare.session.session.ts")
202
+ def test_session_id_length(mock_ts):
203
+ """Test Session ID is 8 characters"""
204
+ mock_ts.pro_api.return_value = Mock()
205
+
206
+ session = Session(credential="test-token")
207
+
208
+ assert len(session.id) == 8
209
+
210
+
211
+ @patch("xfintech.data.source.tushare.session.session.ts")
212
+ def test_session_id_unique(mock_ts):
213
+ """Test different Sessions have different IDs"""
214
+ mock_ts.pro_api.return_value = Mock()
215
+
216
+ session1 = Session(credential="test-token")
217
+ session2 = Session(credential="test-token")
218
+
219
+ assert session1.id != session2.id
220
+
221
+
222
+ # ============================================================================
223
+ # Session Properties Tests
224
+ # ============================================================================
225
+
226
+
227
+ @patch("xfintech.data.source.tushare.session.session.ts")
228
+ def test_session_connected_property_true(mock_ts):
229
+ """Test connected property returns True when connection exists"""
230
+ mock_ts.pro_api.return_value = Mock()
231
+
232
+ session = Session(credential="test-token")
233
+
234
+ assert session.connected is True
235
+
236
+
237
+ @patch("xfintech.data.source.tushare.session.session.ts")
238
+ def test_session_connected_property_false(mock_ts):
239
+ """Test connected property returns False when no connection"""
240
+ mock_ts.pro_api.return_value = Mock()
241
+
242
+ session = Session(credential="test-token")
243
+ session.connection = None
244
+
245
+ assert session.connected is False
246
+
247
+
248
+ @patch("xfintech.data.source.tushare.session.session.ts")
249
+ @patch("xfintech.data.source.tushare.session.session.pd.Timestamp")
250
+ def test_session_duration_property_no_start(mock_timestamp, mock_ts):
251
+ """Test duration returns 0.0 when not started"""
252
+ mock_ts.pro_api.return_value = Mock()
253
+
254
+ session = Session(credential="test-token")
255
+ session.start_at = None
256
+
257
+ assert session.duration == 0.0
258
+
259
+
260
+ @patch("xfintech.data.source.tushare.session.session.ts")
261
+ def test_session_duration_property_ongoing(mock_ts):
262
+ """Test duration calculates correctly for ongoing session"""
263
+ mock_ts.pro_api.return_value = Mock()
264
+
265
+ # Create session
266
+ session = Session(credential="test-token")
267
+
268
+ # Set times directly
269
+ session.start_at = pd.Timestamp("2024-01-15 10:00:00")
270
+ session.finish_at = None
271
+
272
+ # Mock datetime.now to return a specific time
273
+ with patch(
274
+ "xfintech.data.source.tushare.session.session.datetime",
275
+ ) as mock_datetime:
276
+ mock_now = datetime(2024, 1, 15, 10, 0, 10)
277
+ mock_datetime.now.return_value = mock_now
278
+
279
+ duration = session.duration
280
+
281
+ assert duration == 10.0
282
+
283
+
284
+ @patch("xfintech.data.source.tushare.session.session.ts")
285
+ def test_session_duration_property_finished(mock_ts):
286
+ """Test duration calculates correctly for finished session"""
287
+ mock_ts.pro_api.return_value = Mock()
288
+
289
+ session = Session(credential="test-token")
290
+ session.start_at = pd.Timestamp("2024-01-15 10:00:00")
291
+ session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
292
+
293
+ assert session.duration == 30.0
294
+
295
+
296
+ # ============================================================================
297
+ # Session String Representation Tests
298
+ # ============================================================================
299
+
300
+
301
+ @patch("xfintech.data.source.tushare.session.session.ts")
302
+ def test_session_str(mock_ts):
303
+ """Test __str__ returns session ID"""
304
+ mock_ts.pro_api.return_value = Mock()
305
+
306
+ session = Session(credential="test-token")
307
+
308
+ assert str(session) == session.id
309
+
310
+
311
+ @patch("xfintech.data.source.tushare.session.session.ts")
312
+ def test_session_repr(mock_ts):
313
+ """Test __repr__ includes class name, connected status, and mode"""
314
+ mock_ts.pro_api.return_value = Mock()
315
+
316
+ session = Session(credential="test-token", mode="direct")
317
+
318
+ result = repr(session)
319
+ assert "Session" in result
320
+ assert "connected=True" in result
321
+ assert "mode=direct" in result
322
+
323
+
324
+ @patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
325
+ def test_session_repr_relay_mode(mock_relay_client_class):
326
+ """Test __repr__ shows relay mode"""
327
+ mock_client = Mock()
328
+ mock_client.check_health.return_value = True
329
+ mock_relay_client_class.return_value = mock_client
330
+
331
+ session = Session(
332
+ credential="test-token",
333
+ mode="relay",
334
+ relay_url="https://relay.example.com",
335
+ relay_secret="relay-secret",
336
+ )
337
+
338
+ result = repr(session)
339
+ assert "mode=relay" in result
340
+
341
+
342
+ # ============================================================================
343
+ # Session Start/End Methods Tests
344
+ # ============================================================================
345
+
346
+
347
+ @patch("xfintech.data.source.tushare.session.session.ts")
348
+ @patch("xfintech.data.source.tushare.session.session.pd.Timestamp")
349
+ def test_session_start_method(mock_timestamp, mock_ts):
350
+ """Test start method sets start_at"""
351
+ mock_ts.pro_api.return_value = Mock()
352
+ mock_now = pd.Timestamp("2024-01-15 10:00:00")
353
+ mock_timestamp.now.return_value = mock_now
354
+
355
+ session = Session(credential="test-token")
356
+ session.start_at = None
357
+ session.start()
358
+
359
+ assert session.start_at == mock_now
360
+
361
+
362
+ @patch("xfintech.data.source.tushare.session.session.ts")
363
+ @patch("xfintech.data.source.tushare.session.session.pd.Timestamp")
364
+ def test_session_end_method(mock_timestamp, mock_ts):
365
+ """Test end method sets finish_at"""
366
+ mock_ts.pro_api.return_value = Mock()
367
+ mock_now = pd.Timestamp("2024-01-15 10:00:30")
368
+ mock_timestamp.now.return_value = mock_now
369
+
370
+ session = Session(credential="test-token")
371
+ session.end()
372
+
373
+ assert session.finish_at == mock_now
374
+
375
+
376
+ @patch("xfintech.data.source.tushare.session.session.ts")
377
+ def test_session_get_start_iso_none(mock_ts):
378
+ """Test get_start_iso returns None when start_at is None"""
379
+ mock_ts.pro_api.return_value = Mock()
380
+
381
+ session = Session(credential="test-token")
382
+ session.start_at = None
383
+
384
+ assert session.get_start_iso() is None
385
+
386
+
387
+ @patch("xfintech.data.source.tushare.session.session.ts")
388
+ def test_session_get_start_iso_with_value(mock_ts):
389
+ """Test get_start_iso returns ISO format"""
390
+ mock_ts.pro_api.return_value = Mock()
391
+
392
+ session = Session(credential="test-token")
393
+ session.start_at = pd.Timestamp("2024-01-15 10:00:00")
394
+
395
+ result = session.get_start_iso()
396
+ assert "2024-01-15" in result
397
+
398
+
399
+ @patch("xfintech.data.source.tushare.session.session.ts")
400
+ def test_session_get_finish_iso_none(mock_ts):
401
+ """Test get_finish_iso returns None when finish_at is None"""
402
+ mock_ts.pro_api.return_value = Mock()
403
+
404
+ session = Session(credential="test-token")
405
+ session.finish_at = None
406
+
407
+ assert session.get_finish_iso() is None
408
+
409
+
410
+ @patch("xfintech.data.source.tushare.session.session.ts")
411
+ def test_session_get_finish_iso_with_value(mock_ts):
412
+ """Test get_finish_iso returns ISO format"""
413
+ mock_ts.pro_api.return_value = Mock()
414
+
415
+ session = Session(credential="test-token")
416
+ session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
417
+
418
+ result = session.get_finish_iso()
419
+ assert "2024-01-15" in result
420
+
421
+
422
+ # ============================================================================
423
+ # Session Connect/Disconnect Tests
424
+ # ============================================================================
425
+
426
+
427
+ @patch("xfintech.data.source.tushare.session.session.ts")
428
+ def test_session_connect_returns_connection(mock_ts):
429
+ """Test connect returns connection object"""
430
+ mock_api = Mock()
431
+ mock_ts.pro_api.return_value = mock_api
432
+
433
+ session = Session(credential="test-token")
434
+ session.connection = None
435
+
436
+ result = session.connect()
437
+
438
+ assert result is not None
439
+
440
+
441
+ @patch("xfintech.data.source.tushare.session.session.ts")
442
+ def test_session_connect_already_connected(mock_ts):
443
+ """Test connect returns existing connection if already connected"""
444
+ mock_api = Mock()
445
+ mock_ts.pro_api.return_value = mock_api
446
+
447
+ session = Session(credential="test-token")
448
+ first_connection = session.connection
449
+
450
+ # Reset call count
451
+ mock_ts.pro_api.reset_mock()
452
+
453
+ # Try to connect again
454
+ result = session.connect()
455
+
456
+ assert result is first_connection
457
+ # Should not create new connection
458
+ mock_ts.pro_api.assert_not_called()
459
+
460
+
461
+ @patch("xfintech.data.source.tushare.session.session.ts")
462
+ @patch("xfintech.data.source.tushare.session.session.pd.Timestamp")
463
+ def test_session_disconnect_clears_connection(mock_timestamp, mock_ts):
464
+ """Test disconnect clears connection"""
465
+ mock_ts.pro_api.return_value = Mock()
466
+
467
+ session = Session(credential="test-token")
468
+ assert session.connected is True
469
+
470
+ session.disconnect()
471
+
472
+ assert session.connection is None
473
+ assert session.connected is False
474
+
475
+
476
+ @patch("xfintech.data.source.tushare.session.session.ts")
477
+ @patch("xfintech.data.source.tushare.session.session.pd.Timestamp")
478
+ def test_session_disconnect_sets_finish_time(mock_timestamp, mock_ts):
479
+ """Test disconnect sets finish_at"""
480
+ mock_ts.pro_api.return_value = Mock()
481
+ mock_now = pd.Timestamp("2024-01-15 10:00:30")
482
+ mock_timestamp.now.return_value = mock_now
483
+
484
+ session = Session(credential="test-token")
485
+ session.disconnect()
486
+
487
+ assert session.finish_at == mock_now
488
+
489
+
490
+ # ============================================================================
491
+ # Session Describe Method Tests
492
+ # ============================================================================
493
+
494
+
495
+ @patch("xfintech.data.source.tushare.session.session.ts")
496
+ def test_session_describe_basic(mock_ts):
497
+ """Test describe returns basic session info"""
498
+ mock_ts.pro_api.return_value = Mock()
499
+
500
+ session = Session(credential="test-token", mode="direct")
501
+ result = session.describe()
502
+
503
+ assert "id" in result
504
+ assert result["id"] == session.id
505
+ assert "mode" in result
506
+ assert result["mode"] == "direct"
507
+ assert "connected" in result
508
+ assert result["connected"] is True
509
+
510
+
511
+ @patch("xfintech.data.source.tushare.session.session.ts")
512
+ def test_session_describe_masks_credential(mock_ts):
513
+ """Test describe masks credential"""
514
+ mock_ts.pro_api.return_value = Mock()
515
+
516
+ session = Session(credential="test-token")
517
+ result = session.describe()
518
+
519
+ assert result["credential"] == "******"
520
+
521
+
522
+ @patch("xfintech.data.source.tushare.session.session.ts")
523
+ def test_session_describe_no_credential(mock_ts):
524
+ """Test describe handles None credential"""
525
+ mock_ts.pro_api.return_value = Mock()
526
+
527
+ session = Session(credential=None)
528
+ result = session.describe()
529
+
530
+ assert "credential" not in result
531
+
532
+
533
+ @patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
534
+ def test_session_describe_relay_mode(mock_relay_client_class):
535
+ """Test describe includes relay info in relay mode"""
536
+ mock_client = Mock()
537
+ mock_client.check_health.return_value = True
538
+ mock_relay_client_class.return_value = mock_client
539
+
540
+ session = Session(
541
+ credential="test-token",
542
+ mode="relay",
543
+ relay_url="https://relay.example.com",
544
+ relay_secret="relay-secret",
545
+ )
546
+ result = session.describe()
547
+
548
+ assert "relay" in result
549
+ assert result["relay"]["url"] == "https://relay.example.com"
550
+ assert result["relay"]["secret"] == "******"
551
+
552
+
553
+ @patch("xfintech.data.source.tushare.session.session.ts")
554
+ def test_session_describe_with_timestamps(mock_ts):
555
+ """Test describe includes timestamps when available"""
556
+ mock_ts.pro_api.return_value = Mock()
557
+
558
+ session = Session(credential="test-token")
559
+ session.start_at = pd.Timestamp("2024-01-15 10:00:00")
560
+ session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
561
+
562
+ result = session.describe()
563
+
564
+ assert "start_at" in result
565
+ assert "finish_at" in result
566
+
567
+
568
+ @patch("xfintech.data.source.tushare.session.session.ts")
569
+ def test_session_describe_without_finish(mock_ts):
570
+ """Test describe handles ongoing session"""
571
+ mock_ts.pro_api.return_value = Mock()
572
+
573
+ session = Session(credential="test-token")
574
+ session.finish_at = None
575
+
576
+ result = session.describe()
577
+
578
+ assert "start_at" in result
579
+ assert "finish_at" not in result
580
+
581
+
582
+ # ============================================================================
583
+ # Session To Dict Method Tests
584
+ # ============================================================================
585
+
586
+
587
+ @patch("xfintech.data.source.tushare.session.session.ts")
588
+ def test_session_to_dict_structure(mock_ts):
589
+ """Test to_dict returns expected structure"""
590
+ mock_ts.pro_api.return_value = Mock()
591
+
592
+ session = Session(credential="test-token", mode="direct")
593
+ result = session.to_dict()
594
+
595
+ assert "id" in result
596
+ assert "connected" in result
597
+ assert "credential" in result
598
+ assert "mode" in result
599
+ assert "relay" in result
600
+ assert "start_at" in result
601
+ assert "finish_at" in result
602
+ assert "duration" in result
603
+
604
+
605
+ @patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
606
+ def test_session_to_dict_masks_credential(mock_ts):
607
+ """Test to_dict masks credential"""
608
+ mock_ts.pro_api.return_value = Mock()
609
+
610
+ session = Session(credential="test-token")
611
+ result = session.to_dict()
612
+
613
+ assert result["credential"] == "******"
614
+
615
+
616
+ @patch("xfintech.data.source.tushare.session.session.ts")
617
+ def test_session_to_dict_none_credential(mock_ts):
618
+ """Test to_dict handles None credential"""
619
+ mock_ts.pro_api.return_value = Mock()
620
+
621
+ session = Session(credential=None)
622
+ result = session.to_dict()
623
+
624
+ assert result["credential"] is None
625
+
626
+
627
+ @patch("xfintech.data.source.tushare.session.session.ts")
628
+ def test_session_to_dict_includes_duration(mock_ts):
629
+ """Test to_dict includes duration"""
630
+ mock_ts.pro_api.return_value = Mock()
631
+
632
+ session = Session(credential="test-token")
633
+ session.start_at = pd.Timestamp("2024-01-15 10:00:00")
634
+ session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
635
+
636
+ result = session.to_dict()
637
+
638
+ assert result["duration"] == 30.0
639
+
640
+
641
+ # ============================================================================
642
+ # Integration Tests
643
+ # ============================================================================
644
+
645
+
646
+ @patch("xfintech.data.source.tushare.session.session.ts")
647
+ def test_session_full_lifecycle_direct(mock_ts):
648
+ """Test complete session lifecycle in direct mode"""
649
+ mock_api = Mock()
650
+ mock_ts.pro_api.return_value = mock_api
651
+
652
+ # Create session
653
+ session = Session(credential="test-token", mode="direct")
654
+ assert session.connected is True
655
+
656
+ # Use connection
657
+ assert session.connection is mock_api
658
+
659
+ # Disconnect
660
+ session.disconnect()
661
+ assert session.connected is False
662
+ assert session.finish_at is not None
663
+
664
+
665
+ @patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
666
+ def test_session_full_lifecycle_relay(mock_relay_client_class):
667
+ """Test complete session lifecycle in relay mode"""
668
+ mock_client = Mock()
669
+ mock_client.check_health.return_value = True
670
+ mock_relay_client_class.return_value = mock_client
671
+
672
+ # Create session
673
+ session = Session(
674
+ credential="test-token",
675
+ mode="relay",
676
+ relay_url="https://relay.example.com",
677
+ relay_secret="relay-secret",
678
+ )
679
+ assert session.connected is True
680
+ assert isinstance(session.connection, RelayConnection)
681
+
682
+ # Get description
683
+ desc = session.describe()
684
+ assert desc["mode"] == "relay"
685
+ assert desc["relay"]["secret"] == "******"
686
+
687
+ # Disconnect
688
+ session.disconnect()
689
+ assert session.connected is False
690
+
691
+
692
+ @patch("xfintech.data.source.tushare.session.session.ts")
693
+ def test_session_reconnect(mock_ts):
694
+ """Test reconnecting after disconnect"""
695
+ mock_api = Mock()
696
+ mock_ts.pro_api.return_value = mock_api
697
+
698
+ session = Session(credential="test-token")
699
+ session.disconnect()
700
+
701
+ # Reconnect
702
+ session.connect()
703
+
704
+ assert session.connected is True
705
+ assert session.connection is not None