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,586 @@
1
+ """
2
+ 描述:
3
+ - ConnectRefLike 协议和 ConnectRef 类的单元测试。
4
+ - 测试协议的结构、ConnectRef 的功能和边界情况。
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Dict, Optional
10
+
11
+ import pytest
12
+
13
+ from xfintech.connect.common.connectref import ConnectRef, ConnectRefLike
14
+ from xfintech.connect.common.error import ConnectRefKeyError
15
+
16
+ # =============================================================================
17
+ # ConnectRefLike Protocol Tests
18
+ # =============================================================================
19
+
20
+
21
+ def test_connectreflike_is_protocol():
22
+ """测试 ConnectRefLike 是一个协议类"""
23
+ from typing import Protocol
24
+
25
+ assert issubclass(ConnectRefLike.__class__, type(Protocol))
26
+
27
+
28
+ def test_connectreflike_is_runtime_checkable():
29
+ """测试 ConnectRefLike 是运行时可检查的"""
30
+ # Check for protocol marker attributes that exist in Python 3.8+
31
+ assert hasattr(ConnectRefLike, "_is_protocol") or hasattr(ConnectRefLike, "__protocol_attrs__")
32
+
33
+
34
+ def test_connectreflike_has_required_attributes():
35
+ """测试 ConnectRefLike 定义了必需的属性"""
36
+
37
+ annotations = ConnectRefLike.__annotations__
38
+ assert "location" in annotations
39
+ assert "kind" in annotations
40
+
41
+
42
+ def test_connectreflike_has_describe_method():
43
+ """测试 ConnectRefLike 定义了 describe 方法"""
44
+ assert hasattr(ConnectRefLike, "describe")
45
+
46
+
47
+ def test_connectreflike_has_to_dict_method():
48
+ """测试 ConnectRefLike 定义了 to_dict 方法"""
49
+ assert hasattr(ConnectRefLike, "to_dict")
50
+
51
+
52
+ def test_valid_connectreflike_implementation():
53
+ """测试有效的 ConnectRefLike 实现"""
54
+
55
+ class MyRef:
56
+ def __init__(self):
57
+ self.location = "test"
58
+ self.kind = "test"
59
+
60
+ def describe(self) -> Dict[str, Optional[str]]:
61
+ return {"location": self.location}
62
+
63
+ def to_dict(self) -> Dict[str, Optional[str]]:
64
+ return {"location": self.location, "kind": self.kind}
65
+
66
+ ref = MyRef()
67
+ assert isinstance(ref, ConnectRefLike)
68
+
69
+
70
+ def test_invalid_connectreflike_missing_location():
71
+ """测试缺少 location 属性的实现"""
72
+
73
+ class InvalidRef:
74
+ def __init__(self):
75
+ self.kind = "test"
76
+
77
+ def describe(self) -> Dict[str, Optional[str]]:
78
+ return {}
79
+
80
+ def to_dict(self) -> Dict[str, Optional[str]]:
81
+ return {}
82
+
83
+ ref = InvalidRef()
84
+ assert not isinstance(ref, ConnectRefLike)
85
+
86
+
87
+ # =============================================================================
88
+ # ConnectRef Initialization Tests
89
+ # =============================================================================
90
+
91
+
92
+ def test_connectref_init_with_location_only():
93
+ """测试仅使用 location 初始化"""
94
+ ref = ConnectRef(location="test_location")
95
+ assert ref.location == "test_location"
96
+ assert ref.kind is None
97
+
98
+
99
+ def test_connectref_init_with_location_and_kind():
100
+ """测试使用 location 和 kind 初始化"""
101
+ ref = ConnectRef(location="test_location", kind="s3")
102
+ assert ref.location == "test_location"
103
+ assert ref.kind == "s3"
104
+
105
+
106
+ def test_connectref_init_empty_location():
107
+ """测试空字符串 location"""
108
+ ref = ConnectRef(location="")
109
+ assert ref.location == ""
110
+ assert ref.kind is None
111
+
112
+
113
+ def test_connectref_init_none_kind():
114
+ """测试显式 None 的 kind"""
115
+ ref = ConnectRef(location="loc", kind=None)
116
+ assert ref.location == "loc"
117
+ assert ref.kind is None
118
+
119
+
120
+ def test_connectref_is_connectreflike():
121
+ """测试 ConnectRef 是 ConnectRefLike 的实例"""
122
+ ref = ConnectRef(location="test")
123
+ assert isinstance(ref, ConnectRefLike)
124
+
125
+
126
+ # =============================================================================
127
+ # ConnectRef.from_dict Tests
128
+ # =============================================================================
129
+
130
+
131
+ def test_from_dict_with_location_only():
132
+ """测试从仅包含 location 的字典创建"""
133
+ data = {"location": "test_loc"}
134
+ ref = ConnectRef.from_dict(data)
135
+ assert ref.location == "test_loc"
136
+ assert ref.kind is None
137
+
138
+
139
+ def test_from_dict_with_location_and_kind():
140
+ """测试从包含 location 和 kind 的字典创建"""
141
+ data = {"location": "test_loc", "kind": "s3"}
142
+ ref = ConnectRef.from_dict(data)
143
+ assert ref.location == "test_loc"
144
+ assert ref.kind == "s3"
145
+
146
+
147
+ def test_from_dict_missing_location_raises_error():
148
+ """测试缺少 location 键抛出错误"""
149
+ data = {"kind": "s3"}
150
+ with pytest.raises(ConnectRefKeyError) as excinfo:
151
+ ConnectRef.from_dict(data)
152
+ assert "'location' is required in data" in str(excinfo.value)
153
+
154
+
155
+ def test_from_dict_empty_dict_raises_error():
156
+ """测试空字典抛出错误"""
157
+ with pytest.raises(ConnectRefKeyError):
158
+ ConnectRef.from_dict({})
159
+
160
+
161
+ def test_from_dict_with_extra_keys():
162
+ """测试包含额外键的字典"""
163
+ data = {"location": "loc", "kind": "s3", "extra": "ignored"}
164
+ ref = ConnectRef.from_dict(data)
165
+ assert ref.location == "loc"
166
+ assert ref.kind == "s3"
167
+
168
+
169
+ def test_from_dict_none_kind():
170
+ """测试 kind 为 None 的字典"""
171
+ data = {"location": "loc", "kind": None}
172
+ ref = ConnectRef.from_dict(data)
173
+ assert ref.location == "loc"
174
+ assert ref.kind is None
175
+
176
+
177
+ def test_from_dict_location_type_conversion():
178
+ """测试 location 类型转换"""
179
+ data = {"location": 123}
180
+ ref = ConnectRef.from_dict(data)
181
+ assert ref.location == "123"
182
+ assert isinstance(ref.location, str)
183
+
184
+
185
+ def test_from_dict_with_mapping_type():
186
+ """测试使用 Mapping 类型"""
187
+ from collections import OrderedDict
188
+
189
+ data = OrderedDict([("location", "test"), ("kind", "macos")])
190
+ ref = ConnectRef.from_dict(data)
191
+ assert ref.location == "test"
192
+ assert ref.kind == "macos"
193
+
194
+
195
+ # =============================================================================
196
+ # ConnectRef String Representation Tests
197
+ # =============================================================================
198
+
199
+
200
+ def test_str_returns_location():
201
+ """测试 __str__ 返回 location"""
202
+ ref = ConnectRef(location="test_location")
203
+ assert str(ref) == "test_location"
204
+
205
+
206
+ def test_str_with_kind():
207
+ """测试带 kind 的 __str__"""
208
+ ref = ConnectRef(location="test_location", kind="s3")
209
+ assert str(ref) == "test_location"
210
+
211
+
212
+ def test_repr_format():
213
+ """测试 __repr__ 格式"""
214
+ ref = ConnectRef(location="test_location", kind="s3")
215
+ repr_str = repr(ref)
216
+ assert "ConnectRef" in repr_str
217
+ assert "location=test_location" in repr_str
218
+ assert "kind=s3" in repr_str
219
+
220
+
221
+ def test_repr_without_kind():
222
+ """测试没有 kind 的 __repr__"""
223
+ ref = ConnectRef(location="test_location")
224
+ repr_str = repr(ref)
225
+ assert "ConnectRef" in repr_str
226
+ assert "location=test_location" in repr_str
227
+ assert "kind=None" in repr_str
228
+
229
+
230
+ def test_repr_can_be_evaluated():
231
+ """测试 __repr__ 可以被评估(手动检查)"""
232
+ ref = ConnectRef(location="test", kind="s3")
233
+ repr_str = repr(ref)
234
+ # Manual check - repr shows the structure clearly
235
+ assert "test" in repr_str
236
+ assert "s3" in repr_str
237
+
238
+
239
+ # =============================================================================
240
+ # ConnectRef Equality Tests
241
+ # =============================================================================
242
+
243
+
244
+ def test_equality_same_location_and_kind():
245
+ """测试相同 location 和 kind 的相等性"""
246
+ ref1 = ConnectRef(location="test", kind="s3")
247
+ ref2 = ConnectRef(location="test", kind="s3")
248
+ assert ref1 == ref2
249
+
250
+
251
+ def test_equality_same_location_no_kind():
252
+ """测试相同 location 无 kind 的相等性"""
253
+ ref1 = ConnectRef(location="test")
254
+ ref2 = ConnectRef(location="test")
255
+ assert ref1 == ref2
256
+
257
+
258
+ def test_inequality_different_location():
259
+ """测试不同 location 的不相等性"""
260
+ ref1 = ConnectRef(location="test1", kind="s3")
261
+ ref2 = ConnectRef(location="test2", kind="s3")
262
+ assert ref1 != ref2
263
+
264
+
265
+ def test_inequality_different_kind():
266
+ """测试不同 kind 的不相等性"""
267
+ ref1 = ConnectRef(location="test", kind="s3")
268
+ ref2 = ConnectRef(location="test", kind="macos")
269
+ assert ref1 != ref2
270
+
271
+
272
+ def test_inequality_one_has_kind():
273
+ """测试一个有 kind 一个无 kind 的不相等性"""
274
+ ref1 = ConnectRef(location="test", kind="s3")
275
+ ref2 = ConnectRef(location="test")
276
+ assert ref1 != ref2
277
+
278
+
279
+ def test_equality_with_non_connectref():
280
+ """测试与非 ConnectRef 对象的比较"""
281
+ ref = ConnectRef(location="test")
282
+ assert ref != "test"
283
+ assert ref != 123
284
+ assert ref is not None
285
+ assert ref != {"location": "test"}
286
+
287
+
288
+ def test_equality_reflexive():
289
+ """测试相等性的自反性"""
290
+ ref = ConnectRef(location="test", kind="s3")
291
+ assert ref == ref
292
+
293
+
294
+ def test_equality_symmetric():
295
+ """测试相等性的对称性"""
296
+ ref1 = ConnectRef(location="test", kind="s3")
297
+ ref2 = ConnectRef(location="test", kind="s3")
298
+ assert ref1 == ref2
299
+ assert ref2 == ref1
300
+
301
+
302
+ def test_equality_transitive():
303
+ """测试相等性的传递性"""
304
+ ref1 = ConnectRef(location="test", kind="s3")
305
+ ref2 = ConnectRef(location="test", kind="s3")
306
+ ref3 = ConnectRef(location="test", kind="s3")
307
+ assert ref1 == ref2
308
+ assert ref2 == ref3
309
+ assert ref1 == ref3
310
+
311
+
312
+ # =============================================================================
313
+ # ConnectRef Hash Tests
314
+ # =============================================================================
315
+
316
+
317
+ def test_hash_same_values():
318
+ """测试相同值的哈希相同"""
319
+ ref1 = ConnectRef(location="test", kind="s3")
320
+ ref2 = ConnectRef(location="test", kind="s3")
321
+ assert hash(ref1) == hash(ref2)
322
+
323
+
324
+ def test_hash_different_values():
325
+ """测试不同值的哈希可能不同"""
326
+ ref1 = ConnectRef(location="test1", kind="s3")
327
+ ref2 = ConnectRef(location="test2", kind="s3")
328
+ # Hashes might collide, but typically different
329
+ # Just test they are hashable
330
+ assert isinstance(hash(ref1), int)
331
+ assert isinstance(hash(ref2), int)
332
+
333
+
334
+ def test_can_use_in_set():
335
+ """测试可以在集合中使用"""
336
+ ref1 = ConnectRef(location="test1", kind="s3")
337
+ ref2 = ConnectRef(location="test2", kind="s3")
338
+ ref3 = ConnectRef(location="test1", kind="s3")
339
+
340
+ ref_set = {ref1, ref2, ref3}
341
+ assert len(ref_set) == 2 # ref1 and ref3 are equal
342
+
343
+
344
+ def test_can_use_as_dict_key():
345
+ """测试可以作为字典键使用"""
346
+ ref1 = ConnectRef(location="test1", kind="s3")
347
+ ref2 = ConnectRef(location="test2", kind="s3")
348
+
349
+ data = {ref1: "value1", ref2: "value2"}
350
+ assert data[ref1] == "value1"
351
+ assert data[ref2] == "value2"
352
+
353
+
354
+ def test_hash_consistent_with_equality():
355
+ """测试哈希与相等性一致"""
356
+ ref1 = ConnectRef(location="test", kind="s3")
357
+ ref2 = ConnectRef(location="test", kind="s3")
358
+
359
+ if ref1 == ref2:
360
+ assert hash(ref1) == hash(ref2)
361
+
362
+
363
+ # =============================================================================
364
+ # ConnectRef.describe Tests
365
+ # =============================================================================
366
+
367
+
368
+ def test_describe_with_location_only():
369
+ """测试仅 location 的描述"""
370
+ ref = ConnectRef(location="test_location")
371
+ result = ref.describe()
372
+ assert result == {"location": "test_location"}
373
+
374
+
375
+ def test_describe_with_location_and_kind():
376
+ """测试带 kind 的描述"""
377
+ ref = ConnectRef(location="test_location", kind="s3")
378
+ result = ref.describe()
379
+ assert result == {"location": "test_location", "kind": "s3"}
380
+
381
+
382
+ def test_describe_kind_none_not_included():
383
+ """测试 kind 为 None 时不包含在描述中"""
384
+ ref = ConnectRef(location="test", kind=None)
385
+ result = ref.describe()
386
+ assert "kind" not in result
387
+ assert result == {"location": "test"}
388
+
389
+
390
+ def test_describe_returns_dict():
391
+ """测试 describe 返回字典类型"""
392
+ ref = ConnectRef(location="test")
393
+ result = ref.describe()
394
+ assert isinstance(result, dict)
395
+
396
+
397
+ def test_describe_empty_kind_string():
398
+ """测试空字符串 kind"""
399
+ ref = ConnectRef(location="test", kind="")
400
+ result = ref.describe()
401
+ # Empty string is falsy, so not included
402
+ assert "kind" not in result
403
+
404
+
405
+ # =============================================================================
406
+ # ConnectRef.to_dict Tests
407
+ # =============================================================================
408
+
409
+
410
+ def test_to_dict_with_location_only():
411
+ """测试仅 location 的字典转换"""
412
+ ref = ConnectRef(location="test_location")
413
+ result = ref.to_dict()
414
+ assert result == {"location": "test_location"}
415
+
416
+
417
+ def test_to_dict_with_location_and_kind():
418
+ """测试带 kind 的字典转换"""
419
+ ref = ConnectRef(location="test_location", kind="s3")
420
+ result = ref.to_dict()
421
+ assert result == {"location": "test_location", "kind": "s3"}
422
+
423
+
424
+ def test_to_dict_kind_none_not_included():
425
+ """测试 kind 为 None 时不包含"""
426
+ ref = ConnectRef(location="test")
427
+ result = ref.to_dict()
428
+ assert "kind" not in result
429
+
430
+
431
+ def test_to_dict_returns_dict():
432
+ """测试 to_dict 返回字典类型"""
433
+ ref = ConnectRef(location="test")
434
+ result = ref.to_dict()
435
+ assert isinstance(result, dict)
436
+
437
+
438
+ def test_to_dict_roundtrip():
439
+ """测试 to_dict 和 from_dict 往返"""
440
+ original = ConnectRef(location="test_loc", kind="s3")
441
+ data = original.to_dict()
442
+ restored = ConnectRef.from_dict(data)
443
+ assert original == restored
444
+
445
+
446
+ def test_to_dict_roundtrip_no_kind():
447
+ """测试无 kind 的往返"""
448
+ original = ConnectRef(location="test_loc")
449
+ data = original.to_dict()
450
+ restored = ConnectRef.from_dict(data)
451
+ assert original == restored
452
+
453
+
454
+ # =============================================================================
455
+ # ConnectRef Edge Cases
456
+ # =============================================================================
457
+
458
+
459
+ def test_special_characters_in_location():
460
+ """测试 location 中的特殊字符"""
461
+ special_locs = [
462
+ "s3://bucket/key/with/slashes",
463
+ "/local/path/with spaces",
464
+ "~/user/home/path",
465
+ "path\\with\\backslashes",
466
+ "path-with-dashes",
467
+ "path_with_underscores",
468
+ "path.with.dots",
469
+ ]
470
+
471
+ for loc in special_locs:
472
+ ref = ConnectRef(location=loc)
473
+ assert ref.location == loc
474
+
475
+
476
+ def test_unicode_in_location():
477
+ """测试 location 中的 Unicode 字符"""
478
+ ref = ConnectRef(location="路径/文件.txt", kind="中文")
479
+ assert ref.location == "路径/文件.txt"
480
+ assert ref.kind == "中文"
481
+
482
+
483
+ def test_very_long_location():
484
+ """测试非常长的 location"""
485
+ long_loc = "a" * 10000
486
+ ref = ConnectRef(location=long_loc)
487
+ assert ref.location == long_loc
488
+ assert len(ref.location) == 10000
489
+
490
+
491
+ def test_empty_string_location():
492
+ """测试空字符串 location"""
493
+ ref = ConnectRef(location="")
494
+ assert ref.location == ""
495
+ assert str(ref) == ""
496
+
497
+
498
+ def test_whitespace_only_location():
499
+ """测试仅空格的 location"""
500
+ ref = ConnectRef(location=" ")
501
+ assert ref.location == " "
502
+
503
+
504
+ def test_newline_in_location():
505
+ """测试 location 中的换行符"""
506
+ ref = ConnectRef(location="line1\nline2")
507
+ assert ref.location == "line1\nline2"
508
+
509
+
510
+ # =============================================================================
511
+ # Real-World Usage Tests
512
+ # =============================================================================
513
+
514
+
515
+ def test_s3_reference():
516
+ """测试 S3 引用"""
517
+ ref = ConnectRef(location="s3://my-bucket/path/to/object.parquet", kind="s3")
518
+ assert ref.location == "s3://my-bucket/path/to/object.parquet"
519
+ assert ref.kind == "s3"
520
+
521
+
522
+ def test_local_file_reference():
523
+ """测试本地文件引用"""
524
+ ref = ConnectRef(location="/Users/username/data/file.csv", kind="macos")
525
+ assert ref.location == "/Users/username/data/file.csv"
526
+ assert ref.kind == "macos"
527
+
528
+
529
+ def test_relative_path_reference():
530
+ """测试相对路径引用"""
531
+ ref = ConnectRef(location="./data/file.json", kind="local")
532
+ assert ref.location == "./data/file.json"
533
+
534
+
535
+ def test_http_url_reference():
536
+ """测试 HTTP URL 引用"""
537
+ ref = ConnectRef(location="https://example.com/data/file.json", kind="http")
538
+ assert ref.location == "https://example.com/data/file.json"
539
+ assert ref.kind == "http"
540
+
541
+
542
+ def test_multiple_references_in_list():
543
+ """测试列表中的多个引用"""
544
+ refs = [
545
+ ConnectRef(location="loc1", kind="s3"),
546
+ ConnectRef(location="loc2", kind="macos"),
547
+ ConnectRef(location="loc3", kind="s3"),
548
+ ]
549
+
550
+ assert len(refs) == 3
551
+ assert all(isinstance(ref, ConnectRef) for ref in refs)
552
+
553
+
554
+ def test_reference_serialization_workflow():
555
+ """测试引用的序列化工作流"""
556
+ # Create
557
+ ref = ConnectRef(location="s3://bucket/key", kind="s3")
558
+
559
+ # Serialize
560
+ data = ref.to_dict()
561
+ assert isinstance(data, dict)
562
+
563
+ # Store (simulate JSON)
564
+ import json
565
+
566
+ json_str = json.dumps(data)
567
+
568
+ # Restore
569
+ restored_data = json.loads(json_str)
570
+ restored_ref = ConnectRef.from_dict(restored_data)
571
+
572
+ # Verify
573
+ assert restored_ref == ref
574
+
575
+
576
+ def test_reference_in_metadata():
577
+ """测试引用在元数据中的使用"""
578
+ metadata = {
579
+ "source": ConnectRef(location="s3://source/data", kind="s3"),
580
+ "destination": ConnectRef(location="/local/output", kind="macos"),
581
+ }
582
+
583
+ assert isinstance(metadata["source"], ConnectRef)
584
+ assert isinstance(metadata["destination"], ConnectRef)
585
+ assert metadata["source"].kind == "s3"
586
+ assert metadata["destination"].kind == "macos"