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,626 @@
1
+ import pandas as pd
2
+ import pytest
3
+
4
+ from xfintech.data.source.tushare.stock.stocksuspend import StockSuspend
5
+ from xfintech.data.source.tushare.stock.stocksuspend.constant import (
6
+ KEY,
7
+ NAME,
8
+ PAGINATE,
9
+ SOURCE,
10
+ TARGET,
11
+ )
12
+
13
+ # ============================================================================
14
+ # Test Fixtures
15
+ # ============================================================================
16
+
17
+
18
+ class FakeConnection:
19
+ """Fake Tushare connection for testing"""
20
+
21
+ def __init__(self, frame: pd.DataFrame):
22
+ self.frame = frame
23
+
24
+ def suspend_d(self, **kwargs):
25
+ """Mock suspend_d API call"""
26
+ return self.frame
27
+
28
+
29
+ class FakeSession:
30
+ """Fake session for testing"""
31
+
32
+ def __init__(self, connection: FakeConnection):
33
+ self.connection = connection
34
+
35
+
36
+ @pytest.fixture
37
+ def mock_session():
38
+ """Create a mock session with empty data"""
39
+ fake_conn = FakeConnection(frame=pd.DataFrame())
40
+ return FakeSession(fake_conn)
41
+
42
+
43
+ @pytest.fixture
44
+ def sample_source_data():
45
+ """Sample stock suspend/resume data in Tushare format"""
46
+ return pd.DataFrame(
47
+ {
48
+ "ts_code": ["000001.SZ", "000002.SZ", "000001.SZ"],
49
+ "trade_date": ["20200331", "20200331", "20200630"],
50
+ "suspend_timing": ["全天", "全天", "午后"],
51
+ "suspend_type": ["临时停牌", "重大事项", "临时停牌"],
52
+ }
53
+ )
54
+
55
+
56
+ # ============================================================================
57
+ # Initialization Tests
58
+ # ============================================================================
59
+
60
+
61
+ def test_stocksuspend_init_basic(mock_session):
62
+ """Test basic initialization with required session"""
63
+ suspend = StockSuspend(session=mock_session)
64
+ assert suspend.name == NAME
65
+ assert suspend.key == KEY
66
+ assert suspend.source == SOURCE
67
+ assert suspend.target == TARGET
68
+ assert suspend.paginate == PAGINATE
69
+
70
+
71
+ def test_stocksuspend_init_with_params_dict(mock_session):
72
+ """Test initialization with params as dict"""
73
+ params = {"trade_date": "20201231", "ts_code": "000001.SZ"}
74
+ suspend = StockSuspend(session=mock_session, params=params)
75
+ assert suspend.params.get("trade_date") == "20201231"
76
+ assert suspend.params.get("ts_code") == "000001.SZ"
77
+
78
+
79
+ def test_stocksuspend_init_with_params_object(mock_session):
80
+ """Test initialization with params as Params object"""
81
+ from xfintech.data.common.params import Params
82
+
83
+ params = Params(trade_date="20201231")
84
+ suspend = StockSuspend(session=mock_session, params=params)
85
+ assert suspend.params.get("trade_date") == "20201231"
86
+
87
+
88
+ def test_stocksuspend_init_with_date_range(mock_session):
89
+ """Test initialization with date range parameters"""
90
+ params = {"start_date": "20200101", "end_date": "20201231"}
91
+ suspend = StockSuspend(session=mock_session, params=params)
92
+ assert suspend.params.get("start_date") == "20200101"
93
+ assert suspend.params.get("end_date") == "20201231"
94
+
95
+
96
+ def test_stocksuspend_init_with_cache_bool_true(mock_session):
97
+ """Test initialization with cache enabled"""
98
+ suspend = StockSuspend(session=mock_session, cache=True)
99
+ assert suspend.cache is not None
100
+
101
+
102
+ def test_stocksuspend_init_with_cache_bool_false(mock_session):
103
+ """Test initialization with cache disabled"""
104
+ suspend = StockSuspend(session=mock_session, cache=False)
105
+ assert suspend.cache is None
106
+
107
+
108
+ def test_stocksuspend_init_with_cache_dict(mock_session):
109
+ """Test initialization with cache config dict"""
110
+ cache_config = {"path": "/tmp/cache", "key": "test"}
111
+ suspend = StockSuspend(session=mock_session, cache=cache_config)
112
+ assert suspend.cache is not None
113
+
114
+
115
+ def test_stocksuspend_init_default_paginate_limit(mock_session):
116
+ """Test that default pagination limit is set correctly"""
117
+ suspend = StockSuspend(session=mock_session)
118
+ assert suspend.paginate.pagesize == 1000
119
+ assert suspend.paginate.pagelimit == 1000
120
+
121
+
122
+ def test_stocksuspend_init_with_all_params(mock_session):
123
+ """Test initialization with all parameters"""
124
+ params = {"trade_date": "20201231"}
125
+ coolant = {"interval": 0.5}
126
+ retry = {"max_attempts": 3}
127
+ cache = True
128
+
129
+ suspend = StockSuspend(session=mock_session, params=params, coolant=coolant, retry=retry, cache=cache)
130
+ assert suspend.params.get("trade_date") == "20201231"
131
+ assert suspend.cache is not None
132
+
133
+
134
+ def test_stocksuspend_constants():
135
+ """Test that constants are correctly defined"""
136
+ assert NAME == "stocksuspend"
137
+ assert KEY == "/tushare/stocksuspend"
138
+ assert SOURCE.name == "suspend_d"
139
+ assert TARGET.name == "stocksuspend"
140
+ assert PAGINATE.pagesize == 1000
141
+ assert PAGINATE.pagelimit == 1000
142
+
143
+
144
+ # ============================================================================
145
+ # Transform Tests
146
+ # ============================================================================
147
+
148
+
149
+ def test_stocksuspend_transform_basic(sample_source_data):
150
+ """Test basic transformation of suspend/resume data"""
151
+ fake_conn = FakeConnection(frame=sample_source_data)
152
+ session = FakeSession(fake_conn)
153
+ suspend = StockSuspend(session=session)
154
+
155
+ result = suspend.transform(sample_source_data)
156
+
157
+ assert len(result) == 3
158
+ assert "code" in result.columns
159
+ assert "date" in result.columns
160
+ assert "datecode" in result.columns
161
+
162
+
163
+ def test_stocksuspend_transform_code_mapping(sample_source_data):
164
+ """Test that ts_code is correctly mapped to code"""
165
+ fake_conn = FakeConnection(frame=sample_source_data)
166
+ session = FakeSession(fake_conn)
167
+ suspend = StockSuspend(session=session)
168
+
169
+ result = suspend.transform(sample_source_data)
170
+
171
+ assert result.iloc[0]["code"] == "000001.SZ"
172
+ assert result.iloc[1]["code"] == "000001.SZ"
173
+ assert result.iloc[2]["code"] == "000002.SZ"
174
+
175
+
176
+ def test_stocksuspend_transform_date_format(sample_source_data):
177
+ """Test that dates are properly formatted"""
178
+ fake_conn = FakeConnection(frame=sample_source_data)
179
+ session = FakeSession(fake_conn)
180
+ suspend = StockSuspend(session=session)
181
+
182
+ result = suspend.transform(sample_source_data)
183
+
184
+ assert pd.api.types.is_datetime64_any_dtype(result["date"]) is False
185
+ assert result.iloc[0]["date"] == "2020-03-31"
186
+ assert result.iloc[1]["date"] == "2020-06-30"
187
+
188
+
189
+ def test_stocksuspend_transform_datecode_preserved(sample_source_data):
190
+ """Test that datecode is correctly created from trade_date"""
191
+ fake_conn = FakeConnection(frame=sample_source_data)
192
+ session = FakeSession(fake_conn)
193
+ suspend = StockSuspend(session=session)
194
+
195
+ result = suspend.transform(sample_source_data)
196
+
197
+ assert result.iloc[0]["datecode"] == "20200331"
198
+ assert result.iloc[1]["datecode"] == "20200630"
199
+
200
+
201
+ def test_stocksuspend_transform_string_fields(sample_source_data):
202
+ """Test that string fields are properly converted"""
203
+ fake_conn = FakeConnection(frame=sample_source_data)
204
+ session = FakeSession(fake_conn)
205
+ suspend = StockSuspend(session=session)
206
+
207
+ result = suspend.transform(sample_source_data)
208
+
209
+ # After sorting by code and date: 000001.SZ-20200331, 000001.SZ-20200630, 000002.SZ-20200331
210
+ assert result.iloc[0]["suspend_timing"] == "全天"
211
+ assert result.iloc[0]["suspend_type"] == "临时停牌"
212
+ assert result.iloc[1]["suspend_timing"] == "午后" # This is 000001.SZ-20200630
213
+
214
+
215
+ def test_stocksuspend_transform_empty_dataframe():
216
+ """Test transformation with empty dataframe"""
217
+ fake_conn = FakeConnection(frame=pd.DataFrame())
218
+ session = FakeSession(fake_conn)
219
+ suspend = StockSuspend(session=session)
220
+
221
+ result = suspend.transform(pd.DataFrame())
222
+
223
+ assert isinstance(result, pd.DataFrame)
224
+ assert result.empty
225
+ assert len(result.columns) == len(TARGET.list_column_names())
226
+
227
+
228
+ def test_stocksuspend_transform_none_input():
229
+ """Test transformation with None input"""
230
+ fake_conn = FakeConnection(frame=pd.DataFrame())
231
+ session = FakeSession(fake_conn)
232
+ suspend = StockSuspend(session=session)
233
+
234
+ result = suspend.transform(None)
235
+
236
+ assert isinstance(result, pd.DataFrame)
237
+ assert result.empty
238
+
239
+
240
+ def test_stocksuspend_transform_handles_invalid_dates():
241
+ """Test that invalid dates are handled gracefully"""
242
+ data = pd.DataFrame(
243
+ {
244
+ "ts_code": ["000001.SZ"],
245
+ "trade_date": ["invalid"],
246
+ "suspend_timing": ["全天"],
247
+ "suspend_type": ["临时停牌"],
248
+ }
249
+ )
250
+
251
+ fake_conn = FakeConnection(frame=data)
252
+ session = FakeSession(fake_conn)
253
+ suspend = StockSuspend(session=session)
254
+
255
+ result = suspend.transform(data)
256
+
257
+ assert len(result) == 1
258
+ assert pd.isna(result.iloc[0]["date"])
259
+
260
+
261
+ def test_stocksuspend_transform_removes_duplicates(sample_source_data):
262
+ """Test that duplicate rows are removed"""
263
+ # Create data with duplicates
264
+ data = pd.concat([sample_source_data, sample_source_data.iloc[[0]]], ignore_index=True)
265
+
266
+ fake_conn = FakeConnection(frame=data)
267
+ session = FakeSession(fake_conn)
268
+ suspend = StockSuspend(session=session)
269
+
270
+ result = suspend.transform(data)
271
+
272
+ # Should have 3 unique rows, not 4
273
+ assert len(result) == 3
274
+
275
+
276
+ def test_stocksuspend_transform_sorts_by_code_and_date(sample_source_data):
277
+ """Test that output is sorted by code and date"""
278
+ fake_conn = FakeConnection(frame=sample_source_data)
279
+ session = FakeSession(fake_conn)
280
+ suspend = StockSuspend(session=session)
281
+
282
+ result = suspend.transform(sample_source_data)
283
+
284
+ # Check first rows are sorted correctly
285
+ assert result.iloc[0]["code"] == "000001.SZ"
286
+ assert result.iloc[0]["date"] == "2020-03-31"
287
+ assert result.iloc[1]["code"] == "000001.SZ"
288
+ assert result.iloc[1]["date"] == "2020-06-30"
289
+ assert result.iloc[2]["code"] == "000002.SZ"
290
+
291
+
292
+ def test_stocksuspend_transform_resets_index():
293
+ """Test that index is reset after transformation"""
294
+ data = pd.DataFrame(
295
+ {
296
+ "ts_code": ["000001.SZ", "000002.SZ"],
297
+ "trade_date": ["20200331", "20200331"],
298
+ "suspend_timing": ["全天", "全天"],
299
+ "suspend_type": ["临时停牌", "重大事项"],
300
+ },
301
+ index=[5, 10],
302
+ )
303
+
304
+ fake_conn = FakeConnection(frame=data)
305
+ session = FakeSession(fake_conn)
306
+ suspend = StockSuspend(session=session)
307
+
308
+ result = suspend.transform(data)
309
+
310
+ assert result.index.tolist() == [0, 1]
311
+
312
+
313
+ def test_stocksuspend_transform_only_target_columns(sample_source_data):
314
+ """Test that only target columns are in output"""
315
+ fake_conn = FakeConnection(frame=sample_source_data)
316
+ session = FakeSession(fake_conn)
317
+ suspend = StockSuspend(session=session)
318
+
319
+ result = suspend.transform(sample_source_data)
320
+
321
+ expected_cols = set(TARGET.list_column_names())
322
+ actual_cols = set(result.columns)
323
+
324
+ assert actual_cols == expected_cols
325
+
326
+
327
+ # ============================================================================
328
+ # Run Method Tests
329
+ # ============================================================================
330
+
331
+
332
+ def test_stocksuspend_run_basic(sample_source_data):
333
+ """Test basic run() execution"""
334
+ fake_conn = FakeConnection(frame=sample_source_data)
335
+ session = FakeSession(fake_conn)
336
+ suspend = StockSuspend(session=session, params={"trade_date": "20200331"})
337
+
338
+ result = suspend.run()
339
+
340
+ assert isinstance(result, pd.DataFrame)
341
+ assert len(result) > 0
342
+
343
+
344
+ def test_stocksuspend_run_with_cache_hit(sample_source_data):
345
+ """Test that run() returns cached data when available"""
346
+ fake_conn = FakeConnection(frame=sample_source_data)
347
+ session = FakeSession(fake_conn)
348
+ suspend = StockSuspend(session=session, params={"trade_date": "20200331"}, cache=True)
349
+
350
+ # First run should fetch and cache
351
+ result1 = suspend.run()
352
+
353
+ # Second run should return cached data
354
+ result2 = suspend.run()
355
+
356
+ pd.testing.assert_frame_equal(result1, result2)
357
+
358
+
359
+ def test_stocksuspend_run_with_date_range(sample_source_data):
360
+ """Test run() with date range parameters"""
361
+ fake_conn = FakeConnection(frame=sample_source_data)
362
+ session = FakeSession(fake_conn)
363
+ suspend = StockSuspend(session=session, params={"start_date": "20200101", "end_date": "20201231"})
364
+
365
+ result = suspend.run()
366
+
367
+ assert isinstance(result, pd.DataFrame)
368
+
369
+
370
+ def test_stocksuspend_run_with_datetime_params(sample_source_data):
371
+ """Test run() with datetime objects as parameters"""
372
+ from datetime import datetime
373
+
374
+ fake_conn = FakeConnection(frame=sample_source_data)
375
+ session = FakeSession(fake_conn)
376
+ suspend = StockSuspend(
377
+ session=session,
378
+ params={
379
+ "start_date": datetime(2020, 1, 1),
380
+ "end_date": datetime(2020, 12, 31),
381
+ },
382
+ )
383
+
384
+ result = suspend.run()
385
+
386
+ assert isinstance(result, pd.DataFrame)
387
+
388
+
389
+ def test_stocksuspend_run_adds_fields_param(sample_source_data):
390
+ """Test that run() adds fields parameter if not provided"""
391
+ fake_conn = FakeConnection(frame=sample_source_data)
392
+ session = FakeSession(fake_conn)
393
+ suspend = StockSuspend(session=session, params={"trade_date": "20200331"})
394
+
395
+ # Monkey patch _fetchall to capture params
396
+ suspend._fetchall
397
+ captured_params = {}
398
+
399
+ def mock_fetchall(api, **kwargs):
400
+ captured_params.update(kwargs)
401
+ return sample_source_data
402
+
403
+ suspend._fetchall = mock_fetchall
404
+ suspend.run()
405
+
406
+ assert "fields" in captured_params
407
+ assert len(captured_params["fields"]) > 0
408
+
409
+
410
+ def test_stocksuspend_run_sets_cache(sample_source_data):
411
+ """Test that run() saves result to cache"""
412
+ fake_conn = FakeConnection(frame=sample_source_data)
413
+ session = FakeSession(fake_conn)
414
+ suspend = StockSuspend(session=session, params={"trade_date": "20200331"}, cache=True)
415
+
416
+ result = suspend.run()
417
+
418
+ # Cache should be set after run
419
+ cached = suspend._load_cache()
420
+ assert cached is not None
421
+ pd.testing.assert_frame_equal(result, cached)
422
+
423
+
424
+ def test_stocksuspend_run_calls_transform(sample_source_data):
425
+ """Test that run() calls transform method"""
426
+ fake_conn = FakeConnection(frame=sample_source_data)
427
+ session = FakeSession(fake_conn)
428
+ suspend = StockSuspend(session=session, params={"trade_date": "20200331"})
429
+
430
+ # Monkey patch transform to track if it was called
431
+ original_transform = suspend.transform
432
+ transform_called = {"called": False}
433
+
434
+ def mock_transform(data):
435
+ transform_called["called"] = True
436
+ return original_transform(data)
437
+
438
+ suspend.transform = mock_transform
439
+ suspend.run()
440
+
441
+ assert transform_called["called"] is True
442
+
443
+
444
+ def test_stocksuspend_run_uses_suspend_d_api(sample_source_data):
445
+ """Test that run() uses suspend_d API"""
446
+ fake_conn = FakeConnection(frame=sample_source_data)
447
+ session = FakeSession(fake_conn)
448
+ suspend = StockSuspend(session=session, params={"trade_date": "20200331"})
449
+
450
+ # Monkey patch _fetchall to capture API
451
+ captured_api = {"api": None}
452
+
453
+ def mock_fetchall(api, **kwargs):
454
+ captured_api["api"] = api
455
+ return sample_source_data
456
+
457
+ suspend._fetchall = mock_fetchall
458
+ suspend.run()
459
+
460
+ assert captured_api["api"] == session.connection.suspend_d
461
+
462
+
463
+ # ============================================================================
464
+ # Integration Tests
465
+ # ============================================================================
466
+
467
+
468
+ def test_stocksuspend_full_workflow(sample_source_data):
469
+ """Test complete workflow from initialization to output"""
470
+ fake_conn = FakeConnection(frame=sample_source_data)
471
+ session = FakeSession(fake_conn)
472
+
473
+ suspend = StockSuspend(
474
+ session=session,
475
+ params={"trade_date": "20200331"},
476
+ cache=True,
477
+ )
478
+
479
+ result = suspend.run()
480
+
481
+ # Verify output structure
482
+ assert isinstance(result, pd.DataFrame)
483
+ assert len(result) == 3 # Mock returns all data regardless of params
484
+ assert "code" in result.columns
485
+ assert "date" in result.columns
486
+ assert "suspend_timing" in result.columns
487
+ assert "suspend_type" in result.columns
488
+
489
+ # Verify sorting (code, date)
490
+ assert result.iloc[0]["code"] == "000001.SZ"
491
+ assert result.iloc[0]["date"] == "2020-03-31"
492
+ assert result.iloc[1]["code"] == "000001.SZ"
493
+ assert result.iloc[1]["date"] == "2020-06-30"
494
+ assert result.iloc[2]["code"] == "000002.SZ"
495
+
496
+
497
+ def test_stocksuspend_cache_persistence(sample_source_data):
498
+ """Test that cache persists across multiple runs"""
499
+ fake_conn = FakeConnection(frame=sample_source_data)
500
+ session = FakeSession(fake_conn)
501
+ suspend = StockSuspend(session=session, params={"trade_date": "20200331"}, cache=True)
502
+
503
+ # Run once to populate cache
504
+ result1 = suspend.run()
505
+
506
+ # Clear in-memory data to simulate fresh load
507
+ suspend2 = StockSuspend(session=session, params={"trade_date": "20200331"}, cache=True)
508
+ result2 = suspend2.run()
509
+
510
+ pd.testing.assert_frame_equal(result1, result2)
511
+
512
+
513
+ def test_stocksuspend_params_uniqueness(mock_session):
514
+ """Test that different params produce different cache keys"""
515
+ suspend1 = StockSuspend(
516
+ session=mock_session,
517
+ params={"trade_date": "20200331"},
518
+ cache=True,
519
+ )
520
+ suspend2 = StockSuspend(
521
+ session=mock_session,
522
+ params={"trade_date": "20210331"},
523
+ cache=True,
524
+ )
525
+
526
+ # Test that different params are properly stored
527
+ assert suspend1.params.get("trade_date") == "20200331"
528
+ assert suspend2.params.get("trade_date") == "20210331"
529
+ assert suspend1.params.get("trade_date") != suspend2.params.get("trade_date")
530
+
531
+
532
+ def test_stocksuspend_empty_result_handling():
533
+ """Test handling of empty API results"""
534
+ empty_data = pd.DataFrame()
535
+ fake_conn = FakeConnection(frame=empty_data)
536
+ session = FakeSession(fake_conn)
537
+ suspend = StockSuspend(session=session, params={"trade_date": "20200331"})
538
+
539
+ result = suspend.run()
540
+
541
+ assert isinstance(result, pd.DataFrame)
542
+ assert result.empty
543
+ assert len(result.columns) > 0
544
+
545
+
546
+ def test_stocksuspend_large_dataset_handling():
547
+ """Test handling of large datasets"""
548
+ # Create large dataset
549
+ large_data = pd.DataFrame(
550
+ {
551
+ "ts_code": ["000001.SZ"] * 1000,
552
+ "trade_date": ["20200331"] * 1000,
553
+ "suspend_timing": ["全天"] * 1000,
554
+ "suspend_type": ["临时停牌"] * 1000,
555
+ }
556
+ )
557
+
558
+ fake_conn = FakeConnection(frame=large_data)
559
+ session = FakeSession(fake_conn)
560
+ suspend = StockSuspend(session=session, params={"trade_date": "20200331"})
561
+
562
+ result = suspend.run()
563
+
564
+ # Should deduplicate to 1 row
565
+ assert len(result) == 1
566
+
567
+
568
+ def test_stocksuspend_without_cache(sample_source_data):
569
+ """Test that class works correctly without caching"""
570
+ fake_conn = FakeConnection(frame=sample_source_data)
571
+ session = FakeSession(fake_conn)
572
+ suspend = StockSuspend(session=session, params={"trade_date": "20200331"}, cache=False)
573
+
574
+ result = suspend.run()
575
+
576
+ assert isinstance(result, pd.DataFrame)
577
+ assert len(result) > 0
578
+ assert suspend.cache is None
579
+
580
+
581
+ def test_stocksuspend_handles_missing_fields():
582
+ """Test that missing fields don't break transformation"""
583
+ # Data with only subset of fields
584
+ minimal_data = pd.DataFrame(
585
+ {
586
+ "ts_code": ["000001.SZ"],
587
+ "trade_date": ["20200331"],
588
+ "suspend_timing": ["全天"],
589
+ }
590
+ )
591
+
592
+ fake_conn = FakeConnection(frame=minimal_data)
593
+ session = FakeSession(fake_conn)
594
+ suspend = StockSuspend(session=session, params={"trade_date": "20200331"})
595
+
596
+ result = suspend.run()
597
+
598
+ # Should complete without error
599
+ assert len(result) == 1
600
+ # Missing fields should be NaN
601
+ assert pd.isna(result.iloc[0]["suspend_type"])
602
+
603
+
604
+ def test_stocksuspend_api_doc_reference():
605
+ """Test that class correctly references API documentation"""
606
+ assert "doc_id=397" in StockSuspend.__doc__
607
+
608
+
609
+ def test_stocksuspend_crosssection_scale():
610
+ """Test that module is correctly configured as crosssection scale"""
611
+ assert SOURCE.meta["scale"] == "crosssection"
612
+ assert TARGET.meta["scale"] == "crosssection"
613
+
614
+
615
+ def test_stocksuspend_multiple_dates_handling(sample_source_data):
616
+ """Test handling of data with multiple dates"""
617
+ fake_conn = FakeConnection(frame=sample_source_data)
618
+ session = FakeSession(fake_conn)
619
+ suspend = StockSuspend(session=session, params={"start_date": "20200101", "end_date": "20201231"})
620
+
621
+ result = suspend.run()
622
+
623
+ # Should have data for both dates
624
+ assert len(result) == 3
625
+ assert "2020-03-31" in result["date"].values
626
+ assert "2020-06-30" in result["date"].values
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ from xfintech.data.source.tushare.stock.techindex.constant import (
4
+ KEY,
5
+ NAME,
6
+ PAGINATE,
7
+ SOURCE,
8
+ TARGET,
9
+ )
10
+ from xfintech.data.source.tushare.stock.techindex.techindex import TechIndex
11
+
12
+ __all__ = [
13
+ "TechIndex",
14
+ "KEY",
15
+ "NAME",
16
+ "PAGINATE",
17
+ "SOURCE",
18
+ "TARGET",
19
+ ]