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,401 @@
1
+ """
2
+ 描述:
3
+ - SerialiserLike 协议的单元测试。
4
+ - 测试协议的结构、实现和运行时类型检查。
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any
10
+
11
+ from xfintech.serde.common.dataformat import DataFormat
12
+ from xfintech.serde.common.serialiserlike import SerialiserLike
13
+
14
+ # =============================================================================
15
+ # Protocol Structure Tests
16
+ # =============================================================================
17
+
18
+
19
+ def test_serialiserlike_is_protocol():
20
+ """测试 SerialiserLike 是一个协议类"""
21
+ from typing import Protocol
22
+
23
+ assert issubclass(SerialiserLike.__class__, type(Protocol))
24
+
25
+
26
+ def test_serialiserlike_has_serialise_method():
27
+ """测试 SerialiserLike 定义了 serialise 方法"""
28
+ assert hasattr(SerialiserLike, "serialise")
29
+
30
+
31
+ def test_serialiserlike_method_signature():
32
+ """测试 serialise 方法签名"""
33
+ import inspect
34
+
35
+ sig = inspect.signature(SerialiserLike.serialise)
36
+ params = list(sig.parameters.keys())
37
+ assert "data" in params
38
+ assert "format" in params
39
+ assert "kwargs" in params
40
+
41
+
42
+ # =============================================================================
43
+ # Implementation Tests - Valid Implementations
44
+ # =============================================================================
45
+
46
+
47
+ def test_valid_implementation_with_staticmethod():
48
+ """测试使用 staticmethod 的有效实现"""
49
+
50
+ class ValidSerialiser:
51
+ @staticmethod
52
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
53
+ return b"test"
54
+
55
+ instance = ValidSerialiser()
56
+ assert isinstance(instance, SerialiserLike)
57
+
58
+
59
+ def test_valid_implementation_with_classmethod():
60
+ """测试使用 classmethod 的有效实现"""
61
+
62
+ class ValidSerialiser:
63
+ @classmethod
64
+ def serialise(cls, data: Any, format: Any, **kwargs: Any) -> bytes:
65
+ return b"test"
66
+
67
+ instance = ValidSerialiser()
68
+ assert isinstance(instance, SerialiserLike)
69
+
70
+
71
+ def test_valid_implementation_with_instance_method():
72
+ """测试使用实例方法的有效实现"""
73
+
74
+ class ValidSerialiser:
75
+ def serialise(self, data: Any, format: Any, **kwargs: Any) -> bytes:
76
+ return b"test"
77
+
78
+ instance = ValidSerialiser()
79
+ assert isinstance(instance, SerialiserLike)
80
+
81
+
82
+ def test_valid_implementation_can_call_serialise():
83
+ """测试有效实现可以调用 serialise"""
84
+
85
+ class ValidSerialiser:
86
+ @staticmethod
87
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
88
+ return b"serialized"
89
+
90
+ serialiser = ValidSerialiser()
91
+ result = serialiser.serialise({}, DataFormat.JSON)
92
+ assert result == b"serialized"
93
+
94
+
95
+ def test_valid_implementation_with_kwargs():
96
+ """测试有效实现支持 kwargs"""
97
+
98
+ class ValidSerialiser:
99
+ @staticmethod
100
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
101
+ encoding = kwargs.get("encoding", "utf-8")
102
+ return f"encoded:{encoding}".encode()
103
+
104
+ serialiser = ValidSerialiser()
105
+ result = serialiser.serialise({}, DataFormat.JSON, encoding="ascii")
106
+ assert result == b"encoded:ascii"
107
+
108
+
109
+ def test_valid_implementation_with_complex_logic():
110
+ """测试有效实现包含复杂逻辑"""
111
+
112
+ class ComplexSerialiser:
113
+ @staticmethod
114
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
115
+ if format == DataFormat.JSON:
116
+ import json
117
+
118
+ return json.dumps(data).encode()
119
+ elif format == DataFormat.CSV:
120
+ return b"csv,data"
121
+ else:
122
+ return b"unknown"
123
+
124
+ serialiser = ComplexSerialiser()
125
+ assert isinstance(serialiser, SerialiserLike)
126
+ result = serialiser.serialise({"key": "value"}, DataFormat.JSON)
127
+ assert result == b'{"key": "value"}'
128
+
129
+
130
+ # =============================================================================
131
+ # Implementation Tests - Invalid Implementations
132
+ # =============================================================================
133
+
134
+
135
+ def test_invalid_implementation_missing_method():
136
+ """测试缺少 serialise 方法的实现"""
137
+
138
+ class InvalidSerialiser:
139
+ pass
140
+
141
+ instance = InvalidSerialiser()
142
+ assert not isinstance(instance, SerialiserLike)
143
+
144
+
145
+ def test_invalid_implementation_wrong_method_name():
146
+ """测试方法名错误的实现"""
147
+
148
+ class InvalidSerialiser:
149
+ @staticmethod
150
+ def serialize(data: Any, format: Any, **kwargs: Any) -> bytes:
151
+ return b"test"
152
+
153
+ instance = InvalidSerialiser()
154
+ assert not isinstance(instance, SerialiserLike)
155
+
156
+
157
+ def test_property_implementation_is_valid():
158
+ """测试使用 property 的实现也是有效的"""
159
+
160
+ class PropertySerialiser:
161
+ @property
162
+ def serialise(self):
163
+ return lambda data, format, **kwargs: b"test"
164
+
165
+ instance = PropertySerialiser()
166
+ # Python's Protocol accepts properties with callable values
167
+ assert isinstance(instance, SerialiserLike)
168
+
169
+
170
+ # =============================================================================
171
+ # Type Checking Tests
172
+ # =============================================================================
173
+
174
+
175
+ def test_isinstance_with_valid_class():
176
+ """测试 isinstance 检查有效类"""
177
+
178
+ class MySerialiser:
179
+ @staticmethod
180
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
181
+ return b""
182
+
183
+ assert isinstance(MySerialiser(), SerialiserLike)
184
+
185
+
186
+ def test_isinstance_with_invalid_class():
187
+ """测试 isinstance 检查无效类"""
188
+
189
+ class NotSerialiser:
190
+ def other_method(self):
191
+ pass
192
+
193
+ assert not isinstance(NotSerialiser(), SerialiserLike)
194
+
195
+
196
+ def test_isinstance_with_builtin_types():
197
+ """测试 isinstance 检查内置类型"""
198
+ assert not isinstance(str(), SerialiserLike)
199
+ assert not isinstance(int(), SerialiserLike)
200
+ assert not isinstance(list(), SerialiserLike)
201
+ assert not isinstance(dict(), SerialiserLike)
202
+
203
+
204
+ def test_isinstance_with_none():
205
+ """测试 isinstance 检查 None"""
206
+ assert not isinstance(None, SerialiserLike)
207
+
208
+
209
+ # =============================================================================
210
+ # Inheritance Tests
211
+ # =============================================================================
212
+
213
+
214
+ def test_can_inherit_from_protocol():
215
+ """测试可以继承协议"""
216
+
217
+ class BaseSerialiser(SerialiserLike):
218
+ @staticmethod
219
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
220
+ return b"base"
221
+
222
+ instance = BaseSerialiser()
223
+ assert isinstance(instance, SerialiserLike)
224
+
225
+
226
+ def test_inherited_class_can_override():
227
+ """测试继承类可以重写方法"""
228
+
229
+ class BaseSerialiser(SerialiserLike):
230
+ @staticmethod
231
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
232
+ return b"base"
233
+
234
+ class DerivedSerialiser(BaseSerialiser):
235
+ @staticmethod
236
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
237
+ return b"derived"
238
+
239
+ derived = DerivedSerialiser()
240
+ assert isinstance(derived, SerialiserLike)
241
+ assert derived.serialise({}, DataFormat.JSON) == b"derived"
242
+
243
+
244
+ # =============================================================================
245
+ # Edge Cases Tests
246
+ # =============================================================================
247
+
248
+
249
+ def test_implementation_with_default_arguments():
250
+ """测试带默认参数的实现"""
251
+
252
+ class SerialiserWithDefaults:
253
+ @staticmethod
254
+ def serialise(data: Any, format: Any = DataFormat.JSON, **kwargs: Any) -> bytes:
255
+ return b"default"
256
+
257
+ serialiser = SerialiserWithDefaults()
258
+ assert isinstance(serialiser, SerialiserLike)
259
+
260
+
261
+ def test_implementation_with_extra_methods():
262
+ """测试包含额外方法的实现"""
263
+
264
+ class RichSerialiser:
265
+ @staticmethod
266
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
267
+ return b"test"
268
+
269
+ @staticmethod
270
+ def validate(data: Any) -> bool:
271
+ return True
272
+
273
+ serialiser = RichSerialiser()
274
+ assert isinstance(serialiser, SerialiserLike)
275
+
276
+
277
+ def test_implementation_with_attributes():
278
+ """测试包含属性的实现"""
279
+
280
+ class SerialiserWithState:
281
+ def __init__(self):
282
+ self.counter = 0
283
+
284
+ def serialise(self, data: Any, format: Any, **kwargs: Any) -> bytes:
285
+ self.counter += 1
286
+ return b"test"
287
+
288
+ serialiser = SerialiserWithState()
289
+ assert isinstance(serialiser, SerialiserLike)
290
+
291
+
292
+ def test_callable_object_as_implementation():
293
+ """测试可调用对象作为实现"""
294
+
295
+ class CallableSerialiser:
296
+ def serialise(self, data: Any, format: Any, **kwargs: Any) -> bytes:
297
+ return b"callable"
298
+
299
+ instance = CallableSerialiser()
300
+ assert isinstance(instance, SerialiserLike)
301
+
302
+
303
+ # =============================================================================
304
+ # Real-World Usage Tests
305
+ # =============================================================================
306
+
307
+
308
+ def test_parquet_serialiser_implementation():
309
+ """测试 Parquet 序列化器实现"""
310
+
311
+ class ParquetSerialiser:
312
+ @staticmethod
313
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
314
+ if format != DataFormat.PARQUET:
315
+ raise ValueError(f"Unsupported format: {format}")
316
+ # Simulate parquet serialization
317
+ return b"parquet_data"
318
+
319
+ serialiser = ParquetSerialiser()
320
+ assert isinstance(serialiser, SerialiserLike)
321
+ result = serialiser.serialise({}, DataFormat.PARQUET)
322
+ assert result == b"parquet_data"
323
+
324
+
325
+ def test_csv_serialiser_implementation():
326
+ """测试 CSV 序列化器实现"""
327
+
328
+ class CSVSerialiser:
329
+ @staticmethod
330
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
331
+ if format != DataFormat.CSV:
332
+ raise ValueError(f"Unsupported format: {format}")
333
+ # Simulate CSV serialization
334
+ return b"col1,col2\nval1,val2"
335
+
336
+ serialiser = CSVSerialiser()
337
+ assert isinstance(serialiser, SerialiserLike)
338
+ result = serialiser.serialise({}, DataFormat.CSV)
339
+ assert result == b"col1,col2\nval1,val2"
340
+
341
+
342
+ def test_json_serialiser_implementation():
343
+ """测试 JSON 序列化器实现"""
344
+ import json
345
+
346
+ class JSONSerialiser:
347
+ @staticmethod
348
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
349
+ if format != DataFormat.JSON:
350
+ raise ValueError(f"Unsupported format: {format}")
351
+ return json.dumps(data).encode("utf-8")
352
+
353
+ serialiser = JSONSerialiser()
354
+ assert isinstance(serialiser, SerialiserLike)
355
+ result = serialiser.serialise({"test": 123}, DataFormat.JSON)
356
+ assert result == b'{"test": 123}'
357
+
358
+
359
+ def test_multi_format_serialiser():
360
+ """测试多格式序列化器"""
361
+ import json
362
+
363
+ class MultiFormatSerialiser:
364
+ @staticmethod
365
+ def serialise(data: Any, format: Any, **kwargs: Any) -> bytes:
366
+ if format == DataFormat.JSON:
367
+ return json.dumps(data).encode("utf-8")
368
+ elif format == DataFormat.CSV:
369
+ return b"csv_data"
370
+ elif format == DataFormat.PARQUET:
371
+ return b"parquet_data"
372
+ else:
373
+ raise ValueError(f"Unsupported format: {format}")
374
+
375
+ serialiser = MultiFormatSerialiser()
376
+ assert isinstance(serialiser, SerialiserLike)
377
+
378
+ # Test each format
379
+ json_result = serialiser.serialise({"key": "value"}, DataFormat.JSON)
380
+ assert json_result == b'{"key": "value"}'
381
+
382
+ csv_result = serialiser.serialise({}, DataFormat.CSV)
383
+ assert csv_result == b"csv_data"
384
+
385
+ parquet_result = serialiser.serialise({}, DataFormat.PARQUET)
386
+ assert parquet_result == b"parquet_data"
387
+
388
+
389
+ # =============================================================================
390
+ # Protocol Attribute Tests
391
+ # =============================================================================
392
+
393
+
394
+ def test_protocol_module():
395
+ """测试协议所属模块"""
396
+ assert SerialiserLike.__module__ == "xfintech.serde.common.serialiserlike"
397
+
398
+
399
+ def test_protocol_name():
400
+ """测试协议名称"""
401
+ assert SerialiserLike.__name__ == "SerialiserLike"
@@ -0,0 +1,7 @@
1
+ from .pandas import PandasDeserialiser
2
+ from .python import PythonDeserialiser
3
+
4
+ __all__ = [
5
+ "PandasDeserialiser",
6
+ "PythonDeserialiser",
7
+ ]
@@ -0,0 +1,113 @@
1
+ from __future__ import annotations
2
+
3
+ from io import BytesIO, StringIO
4
+ from typing import Any
5
+
6
+ import pandas as pd
7
+
8
+ from xfintech.serde.common.dataformat import DataFormat
9
+ from xfintech.serde.common.deserialiserlike import DeserialiserLike
10
+ from xfintech.serde.common.error import (
11
+ DeserialiserFailedError,
12
+ DeserialiserImportError,
13
+ DeserialiserInputTypeError,
14
+ DeserialiserNotSupportedError,
15
+ )
16
+
17
+
18
+ class PandasDeserialiser(DeserialiserLike):
19
+ """
20
+ 描述:
21
+ - PandasDeserialiser反序列化模块。
22
+ - BYTES -> DataFrame 的转换,支持多种常见数据格式(Parquet、CSV、JSON)。
23
+
24
+ 方法:
25
+ - deserialise(data, format, **kwargs): 通用反序列化方法,支持多种格式。
26
+ - from_parquet(data, **kwargs): 从 Parquet 格式的字节流反序列化为 DataFrame。
27
+ - from_csv(data, **kwargs): 从 CSV 格式的字节流反序列化为 DataFrame。
28
+ - from_json(data, **kwargs): 从 JSON 格式的字节流反序列化为 DataFrame。
29
+
30
+ 例子:
31
+ ```python
32
+ from xfintech.serde.deserialiser.pandas import PandasDeserialiser
33
+ from xfintech.serde.common.dataformat import DataFormat
34
+
35
+ # 使用通用反序列化方法(推荐)
36
+ df = PandasDeserialiser.deserialise(
37
+ bytes,
38
+ format=DataFormat.PARQUET,
39
+ )
40
+
41
+ ```
42
+ """
43
+
44
+ @staticmethod
45
+ def deserialise(
46
+ data: bytes,
47
+ format: DataFormat | str,
48
+ **kwargs: Any,
49
+ ) -> pd.DataFrame:
50
+ if not isinstance(data, bytes):
51
+ msg = f"PandasDeserialiser.deserialise expects bytes, got {type(data)}"
52
+ raise DeserialiserInputTypeError(msg)
53
+
54
+ format = DataFormat.from_any(format)
55
+ if format == DataFormat.PARQUET:
56
+ return PandasDeserialiser.from_parquet(data, **kwargs)
57
+ elif format == DataFormat.CSV:
58
+ return PandasDeserialiser.from_csv(data, **kwargs)
59
+ elif format == DataFormat.JSON:
60
+ return PandasDeserialiser.from_json(data, **kwargs)
61
+ else:
62
+ msg = f"Unsupported DataFormat for deserialization: {format}"
63
+ raise DeserialiserNotSupportedError(msg)
64
+
65
+ @staticmethod
66
+ def from_parquet(
67
+ data: bytes,
68
+ **kwargs: Any,
69
+ ) -> pd.DataFrame:
70
+ buffer = BytesIO(data)
71
+ try:
72
+ output = pd.read_parquet(buffer, **kwargs)
73
+ return output
74
+ except ImportError as e:
75
+ msg = "pyarrow is required for parquet deserialization. install via 'pip install pyarrow'."
76
+ raise DeserialiserImportError(msg) from e
77
+ except Exception as e:
78
+ msg = f"Failed to deserialize data: {e}"
79
+ raise DeserialiserFailedError(msg) from e
80
+
81
+ @staticmethod
82
+ def from_csv(
83
+ data: bytes,
84
+ **kwargs: Any,
85
+ ) -> pd.DataFrame:
86
+ encoding = kwargs.pop("encoding", "utf-8")
87
+ try:
88
+ buffer = StringIO(data.decode(encoding))
89
+ return pd.read_csv(buffer, **kwargs)
90
+ except Exception as e:
91
+ msg = f"Failed to deserialize data: {e}"
92
+ raise DeserialiserFailedError(msg) from e
93
+
94
+ @staticmethod
95
+ def from_json(
96
+ data: bytes,
97
+ **kwargs: Any,
98
+ ) -> pd.DataFrame:
99
+ encoding = kwargs.pop("encoding", "utf-8")
100
+ orient = kwargs.pop("orient", "records")
101
+ lines = kwargs.pop("lines", False)
102
+ try:
103
+ text = data.decode(encoding)
104
+ buf = StringIO(text)
105
+ return pd.read_json(
106
+ buf,
107
+ orient=orient,
108
+ lines=lines,
109
+ **kwargs,
110
+ )
111
+ except Exception as e:
112
+ msg = f"Failed to deserialize data: {e}"
113
+ raise DeserialiserFailedError(msg) from e
@@ -0,0 +1,68 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from typing import Any
5
+
6
+ from xfintech.serde.common.dataformat import DataFormat
7
+ from xfintech.serde.common.deserialiserlike import DeserialiserLike
8
+ from xfintech.serde.common.error import (
9
+ DeserialiserFailedError,
10
+ DeserialiserInputTypeError,
11
+ DeserialiserNotSupportedError,
12
+ )
13
+
14
+
15
+ class PythonDeserialiser(DeserialiserLike):
16
+ """
17
+ 描述:
18
+ - PythonDict反序列化模块。
19
+ - BYTES -> DICT 的单向转换,适用于配置和轻量级数据交换。
20
+
21
+ 方法:
22
+ - deserialise(data, format, **kwargs): 通用反序列化方法,仅支持 JSON 格式。
23
+ - from_json(data, **kwargs): 从 JSON 字节流解码为数据,编码默认 "utf-8"。
24
+
25
+ 例子:
26
+ ```python
27
+ from xfintech.serde.deserialiser.python import PythonDeserialiser
28
+ from xfintech.serde.common.dataformat import DataFormat
29
+
30
+ # 使用通用反序列化方法(推荐)
31
+ data = PythonDeserialiser.deserialise(
32
+ json_bytes,
33
+ format=DataFormat.JSON,
34
+ )
35
+ ```
36
+ """
37
+
38
+ @staticmethod
39
+ def deserialise(
40
+ data: bytes,
41
+ format: DataFormat | str,
42
+ **kwargs: Any,
43
+ ) -> Any:
44
+ if not isinstance(data, bytes):
45
+ msg = f"PythonDeserialiser.deserialise expects bytes, got {type(data)}"
46
+ raise DeserialiserInputTypeError(msg)
47
+ format = DataFormat.from_any(format)
48
+ if format == DataFormat.JSON:
49
+ return PythonDeserialiser.from_json(data, **kwargs)
50
+ else:
51
+ msg = f"Unsupported DataFormat for deserialization: {format}"
52
+ raise DeserialiserNotSupportedError(msg)
53
+
54
+ @staticmethod
55
+ def from_json(
56
+ data: bytes,
57
+ **kwargs: Any,
58
+ ) -> Any:
59
+ encoding = kwargs.pop("encoding", "utf-8")
60
+ payload = data.decode(encoding)
61
+ try:
62
+ return json.loads(
63
+ payload,
64
+ **kwargs,
65
+ )
66
+ except Exception as e:
67
+ msg = f"Failed to deserialize data: {e}"
68
+ raise DeserialiserFailedError(msg) from e
@@ -0,0 +1 @@
1
+ # Tests for deserialiser modules