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,500 @@
1
+ """
2
+ Test suite for RelayClientLike Protocol
3
+ Tests cover protocol definition, compliance checking, and structural typing
4
+ """
5
+
6
+ from typing import Any, Dict
7
+
8
+ from xfintech.data.relay.clientlike import RelayClientLike
9
+
10
+ # ============================================================================
11
+ # Helper Classes for Testing
12
+ # ============================================================================
13
+
14
+
15
+ class CompliantClient:
16
+ """Class that implements RelayClientLike protocol"""
17
+
18
+ def __init__(self):
19
+ self.url = "https://relay.example.com"
20
+ self.secret = "test-secret"
21
+ self.timeout = 180
22
+
23
+ def call(self) -> Any:
24
+ return {"status": "success"}
25
+
26
+
27
+ class PartialClient:
28
+ """Class that partially implements RelayClientLike protocol"""
29
+
30
+ def __init__(self):
31
+ self.url = "https://relay.example.com"
32
+ self.secret = "test-secret"
33
+ # Missing timeout attribute
34
+
35
+ def call(self) -> Any:
36
+ return {"status": "partial"}
37
+
38
+
39
+ class NonCompliantClient:
40
+ """Class that doesn't implement RelayClientLike protocol"""
41
+
42
+ def __init__(self):
43
+ self.endpoint = "https://relay.example.com"
44
+ self.key = "test-key"
45
+
46
+ def execute(self) -> Any:
47
+ return {"status": "non-compliant"}
48
+
49
+
50
+ class MinimalClient:
51
+ """Minimal implementation of RelayClientLike"""
52
+
53
+ url: str = "https://minimal.example.com"
54
+ secret: str = "minimal-secret"
55
+ timeout: int = 60
56
+
57
+ def call(self):
58
+ return None
59
+
60
+
61
+ # ============================================================================
62
+ # Protocol Compliance Tests
63
+ # ============================================================================
64
+
65
+
66
+ def test_relayclientlike_compliant_client():
67
+ """Test that compliant class is recognized as RelayClientLike"""
68
+ client = CompliantClient()
69
+ assert isinstance(client, RelayClientLike)
70
+
71
+
72
+ def test_relayclientlike_partial_client():
73
+ """Test that partial implementation is not recognized as RelayClientLike"""
74
+ client = PartialClient()
75
+ # Missing timeout, so should not be fully compliant
76
+ assert isinstance(client, RelayClientLike) is False
77
+
78
+
79
+ def test_relayclientlike_non_compliant_client():
80
+ """Test that non-compliant class is not recognized as RelayClientLike"""
81
+ client = NonCompliantClient()
82
+ assert isinstance(client, RelayClientLike) is False
83
+
84
+
85
+ def test_relayclientlike_minimal_client():
86
+ """Test minimal implementation is recognized as RelayClientLike"""
87
+ client = MinimalClient()
88
+ assert isinstance(client, RelayClientLike)
89
+
90
+
91
+ # ============================================================================
92
+ # Protocol Attribute Tests
93
+ # ============================================================================
94
+
95
+
96
+ def test_relayclientlike_has_url_attribute():
97
+ """Test RelayClientLike protocol requires url attribute"""
98
+ client = CompliantClient()
99
+ assert hasattr(client, "url")
100
+ assert isinstance(client.url, str)
101
+
102
+
103
+ def test_relayclientlike_has_secret_attribute():
104
+ """Test RelayClientLike protocol requires secret attribute"""
105
+ client = CompliantClient()
106
+ assert hasattr(client, "secret")
107
+ assert isinstance(client.secret, str)
108
+
109
+
110
+ def test_relayclientlike_has_timeout_attribute():
111
+ """Test RelayClientLike protocol requires timeout attribute"""
112
+ client = CompliantClient()
113
+ assert hasattr(client, "timeout")
114
+ assert isinstance(client.timeout, int)
115
+
116
+
117
+ def test_relayclientlike_has_call_method():
118
+ """Test RelayClientLike protocol requires call method"""
119
+ client = CompliantClient()
120
+ assert hasattr(client, "call")
121
+ assert callable(client.call)
122
+
123
+
124
+ # ============================================================================
125
+ # Protocol Method Tests
126
+ # ============================================================================
127
+
128
+
129
+ def test_relayclientlike_call_returns_any():
130
+ """Test call method can return any type"""
131
+ client = CompliantClient()
132
+ result = client.call()
133
+ assert result is not None
134
+
135
+
136
+ def test_relayclientlike_call_execution():
137
+ """Test call method executes correctly"""
138
+ client = CompliantClient()
139
+ result = client.call()
140
+ assert result == {"status": "success"}
141
+
142
+
143
+ # ============================================================================
144
+ # Protocol Usage Tests
145
+ # ============================================================================
146
+
147
+
148
+ def test_relayclientlike_as_type_annotation():
149
+ """Test RelayClientLike can be used as type annotation"""
150
+
151
+ def process_client(client: RelayClientLike) -> Any:
152
+ return client.call()
153
+
154
+ client = CompliantClient()
155
+ result = process_client(client)
156
+
157
+ assert result == {"status": "success"}
158
+
159
+
160
+ def test_relayclientlike_type_checking():
161
+ """Test RelayClientLike enables structural type checking"""
162
+
163
+ def get_client_info(client: RelayClientLike) -> Dict[str, Any]:
164
+ return {"url": client.url, "timeout": client.timeout}
165
+
166
+ client = CompliantClient()
167
+ info = get_client_info(client)
168
+
169
+ assert info["url"] == "https://relay.example.com"
170
+ assert info["timeout"] == 180
171
+
172
+
173
+ def test_relayclientlike_duck_typing():
174
+ """Test RelayClientLike supports duck typing"""
175
+
176
+ class DuckTypedClient:
177
+ def __init__(self):
178
+ self.url = "https://duck.example.com"
179
+ self.secret = "duck-secret"
180
+ self.timeout = 120
181
+
182
+ def call(self):
183
+ return "duck result"
184
+
185
+ client = DuckTypedClient()
186
+ assert isinstance(client, RelayClientLike)
187
+
188
+
189
+ # ============================================================================
190
+ # Protocol Instance Tests
191
+ # ============================================================================
192
+
193
+
194
+ def test_relayclientlike_multiple_implementations():
195
+ """Test multiple classes can implement RelayClientLike"""
196
+
197
+ class Client1:
198
+ url = "https://client1.example.com"
199
+ secret = "secret1"
200
+ timeout = 100
201
+
202
+ def call(self):
203
+ return 1
204
+
205
+ class Client2:
206
+ url = "https://client2.example.com"
207
+ secret = "secret2"
208
+ timeout = 200
209
+
210
+ def call(self):
211
+ return 2
212
+
213
+ client1 = Client1()
214
+ client2 = Client2()
215
+
216
+ assert isinstance(client1, RelayClientLike)
217
+ assert isinstance(client2, RelayClientLike)
218
+
219
+
220
+ def test_relayclientlike_inheritance_not_required():
221
+ """Test classes don't need to inherit from RelayClientLike"""
222
+
223
+ class IndependentClient:
224
+ url = "https://independent.example.com"
225
+ secret = "independent-secret"
226
+ timeout = 150
227
+
228
+ def call(self):
229
+ return "independent"
230
+
231
+ client = IndependentClient()
232
+ # Should be recognized as RelayClientLike due to structural typing
233
+ assert isinstance(client, RelayClientLike)
234
+
235
+
236
+ # ============================================================================
237
+ # Edge Case Tests
238
+ # ============================================================================
239
+
240
+
241
+ def test_relayclientlike_with_extra_attributes():
242
+ """Test class with extra attributes is still RelayClientLike compliant"""
243
+
244
+ class ExtendedClient:
245
+ url = "https://extended.example.com"
246
+ secret = "extended-secret"
247
+ timeout = 200
248
+ extra_attr = "extra"
249
+ another_attr = 42
250
+
251
+ def call(self):
252
+ return "extended"
253
+
254
+ def extra_method(self):
255
+ return "extra"
256
+
257
+ client = ExtendedClient()
258
+ assert isinstance(client, RelayClientLike)
259
+ assert hasattr(client, "extra_attr")
260
+
261
+
262
+ def test_relayclientlike_with_properties():
263
+ """Test class with properties can be RelayClientLike compliant"""
264
+
265
+ class PropertyClient:
266
+ def __init__(self):
267
+ self._url = "https://property.example.com"
268
+ self._secret = "property-secret"
269
+ self._timeout = 180
270
+
271
+ @property
272
+ def url(self):
273
+ return self._url
274
+
275
+ @property
276
+ def secret(self):
277
+ return self._secret
278
+
279
+ @property
280
+ def timeout(self):
281
+ return self._timeout
282
+
283
+ def call(self):
284
+ return "property result"
285
+
286
+ client = PropertyClient()
287
+ assert isinstance(client, RelayClientLike)
288
+
289
+
290
+ def test_relayclientlike_call_with_arguments():
291
+ """Test RelayClientLike call method can accept arguments"""
292
+
293
+ class ArgClient:
294
+ url = "https://arg.example.com"
295
+ secret = "arg-secret"
296
+ timeout = 180
297
+
298
+ def call(self, *args, **kwargs):
299
+ return f"args: {args}, kwargs: {kwargs}"
300
+
301
+ client = ArgClient()
302
+ assert isinstance(client, RelayClientLike)
303
+
304
+
305
+ # ============================================================================
306
+ # Protocol Validation Tests
307
+ # ============================================================================
308
+
309
+
310
+ def test_relayclientlike_missing_url():
311
+ """Test class missing url attribute is not RelayClientLike"""
312
+
313
+ class MissingUrl:
314
+ secret = "secret"
315
+ timeout = 180
316
+
317
+ def call(self):
318
+ return None
319
+
320
+ client = MissingUrl()
321
+ assert not isinstance(client, RelayClientLike)
322
+
323
+
324
+ def test_relayclientlike_missing_secret():
325
+ """Test class missing secret attribute is not RelayClientLike"""
326
+
327
+ class MissingSecret:
328
+ url = "https://example.com"
329
+ timeout = 180
330
+
331
+ def call(self):
332
+ return None
333
+
334
+ client = MissingSecret()
335
+ assert not isinstance(client, RelayClientLike)
336
+
337
+
338
+ def test_relayclientlike_missing_timeout():
339
+ """Test class missing timeout attribute is not RelayClientLike"""
340
+
341
+ class MissingTimeout:
342
+ url = "https://example.com"
343
+ secret = "secret"
344
+
345
+ def call(self):
346
+ return None
347
+
348
+ client = MissingTimeout()
349
+ assert not isinstance(client, RelayClientLike)
350
+
351
+
352
+ def test_relayclientlike_missing_call():
353
+ """Test class missing call method is not RelayClientLike"""
354
+
355
+ class MissingCall:
356
+ url = "https://example.com"
357
+ secret = "secret"
358
+ timeout = 180
359
+
360
+ client = MissingCall()
361
+ assert not isinstance(client, RelayClientLike)
362
+
363
+
364
+ def test_relayclientlike_wrong_attribute_types():
365
+ """Test class with wrong attribute types can still be RelayClientLike"""
366
+
367
+ class WrongTypes:
368
+ url = 123 # Should be string but protocol doesn't enforce at runtime
369
+ secret = ["list"] # Should be string
370
+ timeout = "180" # Should be int
371
+
372
+ def call(self):
373
+ return None
374
+
375
+ client = WrongTypes()
376
+ # runtime_checkable only checks existence, not types
377
+ assert isinstance(client, RelayClientLike)
378
+
379
+
380
+ # ============================================================================
381
+ # Integration Tests
382
+ # ============================================================================
383
+
384
+
385
+ def test_relayclientlike_function_parameter():
386
+ """Test RelayClientLike as function parameter type"""
387
+
388
+ def execute_and_get_url(client: RelayClientLike) -> tuple:
389
+ result = client.call()
390
+ url = client.url
391
+ return result, url
392
+
393
+ client = CompliantClient()
394
+ result, url = execute_and_get_url(client)
395
+
396
+ assert result == {"status": "success"}
397
+ assert url == "https://relay.example.com"
398
+
399
+
400
+ def test_relayclientlike_list_of_clients():
401
+ """Test list of RelayClientLike objects"""
402
+ clients = [CompliantClient(), MinimalClient()]
403
+
404
+ for client in clients:
405
+ assert isinstance(client, RelayClientLike)
406
+ assert callable(client.call)
407
+
408
+
409
+ def test_relayclientlike_runtime_check():
410
+ """Test runtime_checkable allows isinstance checks"""
411
+
412
+ class RuntimeClient:
413
+ url = "https://runtime.example.com"
414
+ secret = "runtime-secret"
415
+ timeout = 180
416
+
417
+ def call(self):
418
+ return "runtime"
419
+
420
+ client = RuntimeClient()
421
+
422
+ # This works because Protocol is runtime_checkable
423
+ assert isinstance(client, RelayClientLike)
424
+
425
+
426
+ def test_relayclientlike_protocol_not_instantiable():
427
+ """Test RelayClientLike protocol itself cannot be instantiated"""
428
+ # Protocols are not meant to be instantiated directly
429
+ # This test verifies the protocol behavior
430
+
431
+ # We can create instances that conform to the protocol
432
+ client = CompliantClient()
433
+ assert isinstance(client, RelayClientLike)
434
+
435
+ # But we can't instantiate the protocol itself
436
+ # (This would fail: client = RelayClientLike())
437
+
438
+
439
+ def test_relayclientlike_with_dataclass():
440
+ """Test RelayClientLike with dataclass"""
441
+ from dataclasses import dataclass
442
+
443
+ @dataclass
444
+ class DataClient:
445
+ url: str = "https://data.example.com"
446
+ secret: str = "data-secret"
447
+ timeout: int = 180
448
+
449
+ def call(self):
450
+ return "data result"
451
+
452
+ client = DataClient()
453
+ assert isinstance(client, RelayClientLike)
454
+
455
+
456
+ def test_relayclientlike_attribute_access():
457
+ """Test accessing protocol attributes"""
458
+ client = CompliantClient()
459
+
460
+ # Can access all protocol-defined attributes
461
+ assert client.url == "https://relay.example.com"
462
+ assert client.secret == "test-secret"
463
+ assert client.timeout == 180
464
+
465
+ # Can call protocol-defined method
466
+ result = client.call()
467
+ assert result is not None
468
+
469
+
470
+ def test_relayclientlike_polymorphism():
471
+ """Test polymorphic behavior with RelayClientLike"""
472
+ clients = [
473
+ CompliantClient(),
474
+ MinimalClient(),
475
+ ]
476
+
477
+ results = [client.call() for client in clients]
478
+
479
+ assert len(results) == 2
480
+ assert results[0] == {"status": "success"}
481
+ assert results[1] is None
482
+
483
+
484
+ # ============================================================================
485
+ # Protocol Documentation Tests
486
+ # ============================================================================
487
+
488
+
489
+ def test_relayclientlike_is_protocol():
490
+ """Test RelayClientLike is a Protocol"""
491
+ from typing import Protocol
492
+
493
+ assert issubclass(RelayClientLike, Protocol)
494
+
495
+
496
+ def test_relayclientlike_is_runtime_checkable():
497
+ """Test RelayClientLike is runtime_checkable"""
498
+
499
+ # Check if the decorator was applied
500
+ assert hasattr(RelayClientLike, "__protocol_attrs__") or hasattr(RelayClientLike, "_is_runtime_protocol")
@@ -0,0 +1,7 @@
1
+ """
2
+ Data source module for xfintech.
3
+
4
+ This module provides access to various financial data sources:
5
+ - tushare: Tushare Pro API data source with comprehensive A-share market data
6
+ - baostock: Baostock data source for alternative market data
7
+ """
@@ -0,0 +1,21 @@
1
+ from .job.job import BaostockJob
2
+ from .session.session import Session
3
+ from .stock.hs300stock.hs300stock import HS300Stock
4
+ from .stock.minuteline.minuteline import Minuteline
5
+ from .stock.stock.stock import Stock
6
+ from .stock.stockinfo.stockinfo import StockInfo
7
+ from .stock.sz50stock.sz50stock import SZ50Stock
8
+ from .stock.tradedate.tradedate import TradeDate
9
+ from .stock.zz500stock.zz500stock import ZZ500Stock
10
+
11
+ __all__ = [
12
+ "Session",
13
+ "HS300Stock",
14
+ "StockInfo",
15
+ "SZ50Stock",
16
+ "Stock",
17
+ "ZZ500Stock",
18
+ "TradeDate",
19
+ "Minuteline",
20
+ "BaostockJob",
21
+ ]
@@ -0,0 +1,5 @@
1
+ from .job import BaostockJob
2
+
3
+ __all__ = [
4
+ "BaostockJob",
5
+ ]