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,664 @@
1
+ import pandas as pd
2
+ import pytest
3
+
4
+ from xfintech.data.source.tushare.stock.stockpledge import StockPledge
5
+ from xfintech.data.source.tushare.stock.stockpledge.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 pledge_stat(self, **kwargs):
25
+ """Mock pledge_stat 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 pledge stat data in Tushare format"""
46
+ return pd.DataFrame(
47
+ {
48
+ "ts_code": ["000014.SZ", "000014.SZ", "600848.SH"],
49
+ "end_date": ["20180928", "20180921", "20180928"],
50
+ "pledge_count": ["23", "24", "15"],
51
+ "unrest_pledge": ["63.16", "63.17", "25.50"],
52
+ "rest_pledge": ["0.0", "0.0", "5.20"],
53
+ "total_share": ["100000.00", "100000.00", "50000.00"],
54
+ "pledge_ratio": ["0.6316", "0.6317", "0.3070"],
55
+ }
56
+ )
57
+
58
+
59
+ # ============================================================================
60
+ # Initialization Tests
61
+ # ============================================================================
62
+
63
+
64
+ def test_stockpledge_init_basic(mock_session):
65
+ """Test basic initialization with required session"""
66
+ pledge = StockPledge(session=mock_session)
67
+ assert pledge.name == NAME
68
+ assert pledge.key == KEY
69
+ assert pledge.source == SOURCE
70
+ assert pledge.target == TARGET
71
+ assert pledge.paginate == PAGINATE
72
+
73
+
74
+ def test_stockpledge_init_with_params_dict(mock_session):
75
+ """Test initialization with params as dict"""
76
+ params = {"ts_code": "000014.SZ", "end_date": "20180928"}
77
+ pledge = StockPledge(session=mock_session, params=params)
78
+ assert pledge.params.get("ts_code") == "000014.SZ"
79
+ assert pledge.params.get("end_date") == "20180928"
80
+
81
+
82
+ def test_stockpledge_init_with_params_object(mock_session):
83
+ """Test initialization with params as Params object"""
84
+ from xfintech.data.common.params import Params
85
+
86
+ params = Params(ts_code="000014.SZ")
87
+ pledge = StockPledge(session=mock_session, params=params)
88
+ assert pledge.params.get("ts_code") == "000014.SZ"
89
+
90
+
91
+ def test_stockpledge_init_with_end_date(mock_session):
92
+ """Test initialization with end_date parameter"""
93
+ params = {"ts_code": "000014.SZ", "end_date": "20180928"}
94
+ pledge = StockPledge(session=mock_session, params=params)
95
+ assert pledge.params.get("end_date") == "20180928"
96
+
97
+
98
+ def test_stockpledge_init_with_cache_bool_true(mock_session):
99
+ """Test initialization with cache enabled"""
100
+ pledge = StockPledge(session=mock_session, cache=True)
101
+ assert pledge.cache is not None
102
+
103
+
104
+ def test_stockpledge_init_with_cache_bool_false(mock_session):
105
+ """Test initialization with cache disabled"""
106
+ pledge = StockPledge(session=mock_session, cache=False)
107
+ assert pledge.cache is None
108
+
109
+
110
+ def test_stockpledge_init_with_cache_dict(mock_session):
111
+ """Test initialization with cache config dict"""
112
+ cache_config = {"path": "/tmp/cache", "key": "test"}
113
+ pledge = StockPledge(session=mock_session, cache=cache_config)
114
+ assert pledge.cache is not None
115
+
116
+
117
+ def test_stockpledge_init_default_paginate_limit(mock_session):
118
+ """Test that default pagination limit is set correctly"""
119
+ pledge = StockPledge(session=mock_session)
120
+ assert pledge.paginate.pagesize == 1000
121
+ assert pledge.paginate.pagelimit == 1000
122
+
123
+
124
+ def test_stockpledge_init_with_all_params(mock_session):
125
+ """Test initialization with all parameters"""
126
+ params = {"ts_code": "000014.SZ", "end_date": "20180928"}
127
+ coolant = {"interval": 0.5}
128
+ retry = {"max_attempts": 3}
129
+ cache = True
130
+
131
+ pledge = StockPledge(session=mock_session, params=params, coolant=coolant, retry=retry, cache=cache)
132
+ assert pledge.params.get("ts_code") == "000014.SZ"
133
+ assert pledge.cache is not None
134
+
135
+
136
+ def test_stockpledge_constants():
137
+ """Test that constants are correctly defined"""
138
+ assert NAME == "stockpledge"
139
+ assert KEY == "/tushare/stockpledge"
140
+ assert SOURCE.name == "pledge_stat"
141
+ assert TARGET.name == "stockpledge"
142
+ assert PAGINATE.pagesize == 1000
143
+ assert PAGINATE.pagelimit == 1000
144
+
145
+
146
+ # ============================================================================
147
+ # Transform Tests
148
+ # ============================================================================
149
+
150
+
151
+ def test_stockpledge_transform_basic(sample_source_data):
152
+ """Test basic transformation of pledge stat data"""
153
+ fake_conn = FakeConnection(frame=sample_source_data)
154
+ session = FakeSession(fake_conn)
155
+ pledge = StockPledge(session=session)
156
+
157
+ result = pledge.transform(sample_source_data)
158
+
159
+ assert len(result) == 3
160
+ assert "code" in result.columns
161
+ assert "date" in result.columns
162
+ assert "datecode" in result.columns
163
+
164
+
165
+ def test_stockpledge_transform_code_mapping(sample_source_data):
166
+ """Test that ts_code is correctly mapped to code"""
167
+ fake_conn = FakeConnection(frame=sample_source_data)
168
+ session = FakeSession(fake_conn)
169
+ pledge = StockPledge(session=session)
170
+
171
+ result = pledge.transform(sample_source_data)
172
+
173
+ assert result.iloc[0]["code"] == "000014.SZ"
174
+ assert result.iloc[2]["code"] == "600848.SH"
175
+
176
+
177
+ def test_stockpledge_transform_date_format(sample_source_data):
178
+ """Test that dates are properly formatted"""
179
+ fake_conn = FakeConnection(frame=sample_source_data)
180
+ session = FakeSession(fake_conn)
181
+ pledge = StockPledge(session=session)
182
+
183
+ result = pledge.transform(sample_source_data)
184
+
185
+ assert pd.api.types.is_datetime64_any_dtype(result["date"]) is False
186
+ # After sorting by code and date: 000014.SZ dates first (21st, 28th), then 600848.SH
187
+ assert result.iloc[0]["date"] == "2018-09-21"
188
+ assert result.iloc[1]["date"] == "2018-09-28"
189
+
190
+
191
+ def test_stockpledge_transform_datecode_preserved(sample_source_data):
192
+ """Test that datecode is correctly created from end_date"""
193
+ fake_conn = FakeConnection(frame=sample_source_data)
194
+ session = FakeSession(fake_conn)
195
+ pledge = StockPledge(session=session)
196
+
197
+ result = pledge.transform(sample_source_data)
198
+
199
+ # After sorting: 000014.SZ dates first (21st, 28th)
200
+ assert result.iloc[0]["datecode"] == "20180921"
201
+ assert result.iloc[1]["datecode"] == "20180928"
202
+
203
+
204
+ def test_stockpledge_transform_numeric_conversions(sample_source_data):
205
+ """Test that numeric fields are properly converted"""
206
+ fake_conn = FakeConnection(frame=sample_source_data)
207
+ session = FakeSession(fake_conn)
208
+ pledge = StockPledge(session=session)
209
+
210
+ result = pledge.transform(sample_source_data)
211
+
212
+ # After sorting: first row is 000014.SZ 20180921
213
+ assert result.iloc[0]["unrest_pledge"] == 63.17
214
+ assert result.iloc[0]["total_share"] == 100000.00
215
+ assert result.iloc[0]["pledge_ratio"] == 0.6317
216
+ assert pd.api.types.is_numeric_dtype(result["unrest_pledge"])
217
+
218
+
219
+ def test_stockpledge_transform_integer_field(sample_source_data):
220
+ """Test that integer field is properly converted"""
221
+ fake_conn = FakeConnection(frame=sample_source_data)
222
+ session = FakeSession(fake_conn)
223
+ pledge = StockPledge(session=session)
224
+
225
+ result = pledge.transform(sample_source_data)
226
+
227
+ # After sorting: first row is 000014.SZ 20180921 (count=24)
228
+ assert result.iloc[0]["pledge_count"] == 24
229
+ assert result.iloc[1]["pledge_count"] == 23
230
+ assert pd.api.types.is_integer_dtype(result["pledge_count"])
231
+
232
+
233
+ def test_stockpledge_transform_empty_dataframe():
234
+ """Test transformation with empty dataframe"""
235
+ fake_conn = FakeConnection(frame=pd.DataFrame())
236
+ session = FakeSession(fake_conn)
237
+ pledge = StockPledge(session=session)
238
+
239
+ result = pledge.transform(pd.DataFrame())
240
+
241
+ assert isinstance(result, pd.DataFrame)
242
+ assert result.empty
243
+ assert len(result.columns) == len(TARGET.list_column_names())
244
+
245
+
246
+ def test_stockpledge_transform_none_input():
247
+ """Test transformation with None input"""
248
+ fake_conn = FakeConnection(frame=pd.DataFrame())
249
+ session = FakeSession(fake_conn)
250
+ pledge = StockPledge(session=session)
251
+
252
+ result = pledge.transform(None)
253
+
254
+ assert isinstance(result, pd.DataFrame)
255
+ assert result.empty
256
+
257
+
258
+ def test_stockpledge_transform_handles_invalid_dates():
259
+ """Test that invalid dates are handled gracefully"""
260
+ data = pd.DataFrame(
261
+ {
262
+ "ts_code": ["000014.SZ"],
263
+ "end_date": ["invalid"],
264
+ "pledge_count": ["23"],
265
+ "unrest_pledge": ["63.16"],
266
+ "rest_pledge": ["0.0"],
267
+ "total_share": ["100000.00"],
268
+ "pledge_ratio": ["0.6316"],
269
+ }
270
+ )
271
+
272
+ fake_conn = FakeConnection(frame=data)
273
+ session = FakeSession(fake_conn)
274
+ pledge = StockPledge(session=session)
275
+
276
+ result = pledge.transform(data)
277
+
278
+ assert len(result) == 1
279
+ assert pd.isna(result.iloc[0]["date"])
280
+
281
+
282
+ def test_stockpledge_transform_removes_duplicates(sample_source_data):
283
+ """Test that duplicate rows are removed"""
284
+ # Create data with duplicates
285
+ data = pd.concat([sample_source_data, sample_source_data.iloc[[0]]], ignore_index=True)
286
+
287
+ fake_conn = FakeConnection(frame=data)
288
+ session = FakeSession(fake_conn)
289
+ pledge = StockPledge(session=session)
290
+
291
+ result = pledge.transform(data)
292
+
293
+ # Should have 3 unique rows, not 4
294
+ assert len(result) == 3
295
+
296
+
297
+ def test_stockpledge_transform_sorts_by_code_and_date(sample_source_data):
298
+ """Test that output is sorted by code and date"""
299
+ fake_conn = FakeConnection(frame=sample_source_data)
300
+ session = FakeSession(fake_conn)
301
+ pledge = StockPledge(session=session)
302
+
303
+ result = pledge.transform(sample_source_data)
304
+
305
+ # Check sorting: 000014.SZ dates first, then 600848.SH
306
+ assert result.iloc[0]["code"] == "000014.SZ"
307
+ assert result.iloc[0]["date"] == "2018-09-21"
308
+ assert result.iloc[1]["code"] == "000014.SZ"
309
+ assert result.iloc[1]["date"] == "2018-09-28"
310
+ assert result.iloc[2]["code"] == "600848.SH"
311
+
312
+
313
+ def test_stockpledge_transform_resets_index():
314
+ """Test that index is reset after transformation"""
315
+ data = pd.DataFrame(
316
+ {
317
+ "ts_code": ["000014.SZ", "600848.SH"],
318
+ "end_date": ["20180928", "20180928"],
319
+ "pledge_count": ["23", "15"],
320
+ "unrest_pledge": ["63.16", "25.50"],
321
+ "rest_pledge": ["0.0", "5.20"],
322
+ "total_share": ["100000.00", "50000.00"],
323
+ "pledge_ratio": ["0.6316", "0.3070"],
324
+ },
325
+ index=[5, 10],
326
+ )
327
+
328
+ fake_conn = FakeConnection(frame=data)
329
+ session = FakeSession(fake_conn)
330
+ pledge = StockPledge(session=session)
331
+
332
+ result = pledge.transform(data)
333
+
334
+ assert result.index.tolist() == [0, 1]
335
+
336
+
337
+ def test_stockpledge_transform_only_target_columns(sample_source_data):
338
+ """Test that only target columns are in output"""
339
+ fake_conn = FakeConnection(frame=sample_source_data)
340
+ session = FakeSession(fake_conn)
341
+ pledge = StockPledge(session=session)
342
+
343
+ result = pledge.transform(sample_source_data)
344
+
345
+ expected_cols = set(TARGET.list_column_names())
346
+ actual_cols = set(result.columns)
347
+
348
+ assert actual_cols == expected_cols
349
+
350
+
351
+ # ============================================================================
352
+ # Run Method Tests
353
+ # ============================================================================
354
+
355
+
356
+ def test_stockpledge_run_basic(sample_source_data):
357
+ """Test basic run() execution"""
358
+ fake_conn = FakeConnection(frame=sample_source_data)
359
+ session = FakeSession(fake_conn)
360
+ pledge = StockPledge(session=session, params={"ts_code": "000014.SZ"})
361
+
362
+ result = pledge.run()
363
+
364
+ assert isinstance(result, pd.DataFrame)
365
+ assert len(result) > 0
366
+
367
+
368
+ def test_stockpledge_run_with_cache_hit(sample_source_data):
369
+ """Test that run() returns cached data when available"""
370
+ fake_conn = FakeConnection(frame=sample_source_data)
371
+ session = FakeSession(fake_conn)
372
+ pledge = StockPledge(session=session, params={"ts_code": "000014.SZ"}, cache=True)
373
+
374
+ # First run should fetch and cache
375
+ result1 = pledge.run()
376
+
377
+ # Second run should return cached data
378
+ result2 = pledge.run()
379
+
380
+ pd.testing.assert_frame_equal(result1, result2)
381
+
382
+
383
+ def test_stockpledge_run_with_end_date(sample_source_data):
384
+ """Test run() with end_date parameter"""
385
+ fake_conn = FakeConnection(frame=sample_source_data)
386
+ session = FakeSession(fake_conn)
387
+ pledge = StockPledge(session=session, params={"end_date": "20180928"})
388
+
389
+ result = pledge.run()
390
+
391
+ assert isinstance(result, pd.DataFrame)
392
+
393
+
394
+ def test_stockpledge_run_with_datetime_params(sample_source_data):
395
+ """Test run() with datetime objects as parameters"""
396
+ from datetime import datetime
397
+
398
+ fake_conn = FakeConnection(frame=sample_source_data)
399
+ session = FakeSession(fake_conn)
400
+ pledge = StockPledge(
401
+ session=session,
402
+ params={
403
+ "ts_code": "000014.SZ",
404
+ "end_date": datetime(2018, 9, 28),
405
+ },
406
+ )
407
+
408
+ result = pledge.run()
409
+
410
+ assert isinstance(result, pd.DataFrame)
411
+
412
+
413
+ def test_stockpledge_run_adds_fields_param(sample_source_data):
414
+ """Test that run() adds fields parameter if not provided"""
415
+ fake_conn = FakeConnection(frame=sample_source_data)
416
+ session = FakeSession(fake_conn)
417
+ pledge = StockPledge(session=session, params={"ts_code": "000014.SZ"})
418
+
419
+ # Monkey patch _fetchall to capture params
420
+ pledge._fetchall
421
+ captured_params = {}
422
+
423
+ def mock_fetchall(api, **kwargs):
424
+ captured_params.update(kwargs)
425
+ return sample_source_data
426
+
427
+ pledge._fetchall = mock_fetchall
428
+ pledge.run()
429
+
430
+ assert "fields" in captured_params
431
+ assert len(captured_params["fields"]) > 0
432
+
433
+
434
+ def test_stockpledge_run_sets_cache(sample_source_data):
435
+ """Test that run() saves result to cache"""
436
+ fake_conn = FakeConnection(frame=sample_source_data)
437
+ session = FakeSession(fake_conn)
438
+ pledge = StockPledge(session=session, params={"ts_code": "000014.SZ"}, cache=True)
439
+
440
+ result = pledge.run()
441
+
442
+ # Cache should be set after run
443
+ cached = pledge._load_cache()
444
+ assert cached is not None
445
+ pd.testing.assert_frame_equal(result, cached)
446
+
447
+
448
+ def test_stockpledge_run_calls_transform(sample_source_data):
449
+ """Test that run() calls transform method"""
450
+ fake_conn = FakeConnection(frame=sample_source_data)
451
+ session = FakeSession(fake_conn)
452
+ pledge = StockPledge(session=session, params={"ts_code": "000014.SZ"})
453
+
454
+ # Monkey patch transform to track if it was called
455
+ original_transform = pledge.transform
456
+ transform_called = {"called": False}
457
+
458
+ def mock_transform(data):
459
+ transform_called["called"] = True
460
+ return original_transform(data)
461
+
462
+ pledge.transform = mock_transform
463
+ pledge.run()
464
+
465
+ assert transform_called["called"] is True
466
+
467
+
468
+ def test_stockpledge_run_uses_pledge_stat_api(sample_source_data):
469
+ """Test that run() uses pledge_stat API"""
470
+ fake_conn = FakeConnection(frame=sample_source_data)
471
+ session = FakeSession(fake_conn)
472
+ pledge = StockPledge(session=session, params={"ts_code": "000014.SZ"})
473
+
474
+ # Monkey patch _fetchall to capture API
475
+ captured_api = {"api": None}
476
+
477
+ def mock_fetchall(api, **kwargs):
478
+ captured_api["api"] = api
479
+ return sample_source_data
480
+
481
+ pledge._fetchall = mock_fetchall
482
+ pledge.run()
483
+
484
+ assert captured_api["api"] == session.connection.pledge_stat
485
+
486
+
487
+ # ============================================================================
488
+ # Integration Tests
489
+ # ============================================================================
490
+
491
+
492
+ def test_stockpledge_full_workflow(sample_source_data):
493
+ """Test complete workflow from initialization to output"""
494
+ fake_conn = FakeConnection(frame=sample_source_data)
495
+ session = FakeSession(fake_conn)
496
+
497
+ pledge = StockPledge(
498
+ session=session,
499
+ params={"ts_code": "000014.SZ"},
500
+ cache=True,
501
+ )
502
+
503
+ result = pledge.run()
504
+
505
+ # Verify output structure
506
+ assert isinstance(result, pd.DataFrame)
507
+ assert len(result) == 3
508
+ assert "code" in result.columns
509
+ assert "date" in result.columns
510
+ assert "pledge_count" in result.columns
511
+ assert "pledge_ratio" in result.columns
512
+
513
+ # Verify data types
514
+ assert pd.api.types.is_numeric_dtype(result["pledge_ratio"])
515
+ assert pd.api.types.is_integer_dtype(result["pledge_count"])
516
+
517
+
518
+ def test_stockpledge_cache_persistence(sample_source_data):
519
+ """Test that cache persists across multiple runs"""
520
+ fake_conn = FakeConnection(frame=sample_source_data)
521
+ session = FakeSession(fake_conn)
522
+ pledge = StockPledge(session=session, params={"ts_code": "000014.SZ"}, cache=True)
523
+
524
+ # Run once to populate cache
525
+ result1 = pledge.run()
526
+
527
+ # Clear in-memory data to simulate fresh load
528
+ pledge2 = StockPledge(session=session, params={"ts_code": "000014.SZ"}, cache=True)
529
+ result2 = pledge2.run()
530
+
531
+ pd.testing.assert_frame_equal(result1, result2)
532
+
533
+
534
+ def test_stockpledge_params_uniqueness(mock_session):
535
+ """Test that different params produce different cache keys"""
536
+ pledge1 = StockPledge(
537
+ session=mock_session,
538
+ params={"ts_code": "000014.SZ"},
539
+ cache=True,
540
+ )
541
+ pledge2 = StockPledge(
542
+ session=mock_session,
543
+ params={"ts_code": "600848.SH"},
544
+ cache=True,
545
+ )
546
+
547
+ # Test that different params are properly stored
548
+ assert pledge1.params.get("ts_code") == "000014.SZ"
549
+ assert pledge2.params.get("ts_code") == "600848.SH"
550
+ assert pledge1.params.get("ts_code") != pledge2.params.get("ts_code")
551
+
552
+
553
+ def test_stockpledge_empty_result_handling():
554
+ """Test handling of empty API results"""
555
+ empty_data = pd.DataFrame()
556
+ fake_conn = FakeConnection(frame=empty_data)
557
+ session = FakeSession(fake_conn)
558
+ pledge = StockPledge(session=session, params={"ts_code": "000014.SZ"})
559
+
560
+ result = pledge.run()
561
+
562
+ assert isinstance(result, pd.DataFrame)
563
+ assert result.empty
564
+ assert len(result.columns) > 0
565
+
566
+
567
+ def test_stockpledge_large_dataset_handling():
568
+ """Test handling of large datasets"""
569
+ # Create large dataset
570
+ large_data = pd.DataFrame(
571
+ {
572
+ "ts_code": ["000014.SZ"] * 1000,
573
+ "end_date": ["20180928"] * 1000,
574
+ "pledge_count": ["23"] * 1000,
575
+ "unrest_pledge": ["63.16"] * 1000,
576
+ "rest_pledge": ["0.0"] * 1000,
577
+ "total_share": ["100000.00"] * 1000,
578
+ "pledge_ratio": ["0.6316"] * 1000,
579
+ }
580
+ )
581
+
582
+ fake_conn = FakeConnection(frame=large_data)
583
+ session = FakeSession(fake_conn)
584
+ pledge = StockPledge(session=session, params={"ts_code": "000014.SZ"})
585
+
586
+ result = pledge.run()
587
+
588
+ # Should deduplicate to 1 row
589
+ assert len(result) == 1
590
+
591
+
592
+ def test_stockpledge_without_cache(sample_source_data):
593
+ """Test that class works correctly without caching"""
594
+ fake_conn = FakeConnection(frame=sample_source_data)
595
+ session = FakeSession(fake_conn)
596
+ pledge = StockPledge(session=session, params={"ts_code": "000014.SZ"}, cache=False)
597
+
598
+ result = pledge.run()
599
+
600
+ assert isinstance(result, pd.DataFrame)
601
+ assert len(result) > 0
602
+ assert pledge.cache is None
603
+
604
+
605
+ def test_stockpledge_handles_missing_fields():
606
+ """Test that missing fields don't break transformation"""
607
+ # Data with only subset of fields
608
+ minimal_data = pd.DataFrame(
609
+ {
610
+ "ts_code": ["000014.SZ"],
611
+ "end_date": ["20180928"],
612
+ "pledge_count": ["23"],
613
+ "unrest_pledge": ["63.16"],
614
+ }
615
+ )
616
+
617
+ fake_conn = FakeConnection(frame=minimal_data)
618
+ session = FakeSession(fake_conn)
619
+ pledge = StockPledge(session=session, params={"ts_code": "000014.SZ"})
620
+
621
+ result = pledge.run()
622
+
623
+ # Should complete without error
624
+ assert len(result) == 1
625
+ # Missing fields should be NaN
626
+ assert pd.isna(result.iloc[0]["rest_pledge"])
627
+
628
+
629
+ def test_stockpledge_api_doc_reference():
630
+ """Test that class correctly references API documentation"""
631
+ assert "doc_id=110" in StockPledge.__doc__
632
+
633
+
634
+ def test_stockpledge_crosssection_scale():
635
+ """Test that module is correctly configured as crosssection scale"""
636
+ assert SOURCE.meta["scale"] == "crosssection"
637
+ assert TARGET.meta["scale"] == "crosssection"
638
+
639
+
640
+ def test_stockpledge_multiple_stocks_handling(sample_source_data):
641
+ """Test handling of data with multiple stocks"""
642
+ fake_conn = FakeConnection(frame=sample_source_data)
643
+ session = FakeSession(fake_conn)
644
+ pledge = StockPledge(session=session, params={"end_date": "20180928"})
645
+
646
+ result = pledge.run()
647
+
648
+ # Should have data for both stocks
649
+ assert len(result) == 3
650
+ assert "000014.SZ" in result["code"].values
651
+ assert "600848.SH" in result["code"].values
652
+
653
+
654
+ def test_stockpledge_handles_zero_values(sample_source_data):
655
+ """Test that zero values in numeric fields are handled correctly"""
656
+ fake_conn = FakeConnection(frame=sample_source_data)
657
+ session = FakeSession(fake_conn)
658
+ pledge = StockPledge(session=session)
659
+
660
+ result = pledge.transform(sample_source_data)
661
+
662
+ # Check that zero values are preserved (not treated as missing)
663
+ zero_rest_rows = result[result["rest_pledge"] == 0.0]
664
+ assert len(zero_rest_rows) == 2
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+ from xfintech.data.source.tushare.stock.stockpledgedetail.constant import (
4
+ KEY,
5
+ NAME,
6
+ PAGINATE,
7
+ SOURCE,
8
+ TARGET,
9
+ )
10
+ from xfintech.data.source.tushare.stock.stockpledgedetail.stockpledgedetail import (
11
+ StockPledgeDetail,
12
+ )
13
+
14
+ __all__ = [
15
+ "StockPledgeDetail",
16
+ "KEY",
17
+ "NAME",
18
+ "PAGINATE",
19
+ "SOURCE",
20
+ "TARGET",
21
+ ]