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,681 @@
1
+ import pickle
2
+ import tempfile
3
+ from pathlib import Path
4
+
5
+ from xfintech.data.common.cache import Cache
6
+
7
+ # ==================== Cache Initialization Tests ====================
8
+
9
+
10
+ def test_cache_init_default():
11
+ """Test Cache initialization with default values"""
12
+ cache = Cache()
13
+
14
+ assert cache.identifier is not None
15
+ assert len(cache.identifier) == 12
16
+ assert cache.path is not None
17
+ assert cache.path.exists()
18
+ assert cache.path.is_dir()
19
+
20
+
21
+ def test_cache_init_custom_path():
22
+ """Test Cache initialization with custom path"""
23
+ with tempfile.TemporaryDirectory() as tmpdir:
24
+ custom_path = Path(tmpdir) / "custom_cache"
25
+ cache = Cache(path=custom_path)
26
+
27
+ assert cache.path.parent == custom_path
28
+ assert cache.path.exists()
29
+ assert str(custom_path) in str(cache.path)
30
+
31
+
32
+ def test_cache_init_creates_directory():
33
+ """Test Cache creates directory if it doesn't exist"""
34
+ with tempfile.TemporaryDirectory() as tmpdir:
35
+ new_path = Path(tmpdir) / "new" / "nested" / "path"
36
+ cache = Cache(path=new_path)
37
+
38
+ assert cache.path.exists()
39
+ assert cache.path.is_dir()
40
+
41
+
42
+ def test_cache_unique_identifiers():
43
+ """Test different Cache instances have unique identifiers"""
44
+ cache1 = Cache()
45
+ cache2 = Cache()
46
+
47
+ assert cache1.identifier != cache2.identifier
48
+ assert cache1.path != cache2.path
49
+
50
+
51
+ def test_cache_identifier_format():
52
+ """Test identifier is 12-character hex string"""
53
+ cache = Cache()
54
+
55
+ assert len(cache.identifier) == 12
56
+ # Should be valid hex
57
+ int(cache.identifier, 16)
58
+
59
+
60
+ # ==================== Resolve Methods Tests ====================
61
+
62
+
63
+ def test_cache_resolve_identifier():
64
+ """Test _resolve_identifier generates valid UUID hex"""
65
+ cache = Cache()
66
+ identifier = cache._resolve_identifier()
67
+
68
+ assert isinstance(identifier, str)
69
+ assert len(identifier) == 12
70
+ # Should be valid hex
71
+ int(identifier, 16)
72
+
73
+
74
+ def test_cache_resolve_path_with_none():
75
+ """Test _resolve_path with None uses default"""
76
+ cache = Cache()
77
+ path = cache._resolve_path(None)
78
+
79
+ assert path.exists()
80
+ assert str(Cache.DEFAULT_PARENT) in str(path)
81
+
82
+
83
+ def test_cache_resolve_path_with_string():
84
+ """Test _resolve_path with string path"""
85
+ with tempfile.TemporaryDirectory() as tmpdir:
86
+ cache = Cache()
87
+ path = cache._resolve_path(tmpdir)
88
+
89
+ assert path.exists()
90
+ assert str(tmpdir) in str(path)
91
+ assert cache.identifier in str(path)
92
+
93
+
94
+ def test_cache_resolve_path_with_path_object():
95
+ """Test _resolve_path with Path object"""
96
+ with tempfile.TemporaryDirectory() as tmpdir:
97
+ cache = Cache()
98
+ path = cache._resolve_path(Path(tmpdir))
99
+
100
+ assert path.exists()
101
+ assert isinstance(path, Path)
102
+
103
+
104
+ # ==================== Get Unit Tests ====================
105
+
106
+
107
+ def test_cache_get_unit():
108
+ """Test get_unit returns correct path"""
109
+ cache = Cache()
110
+ unit_path = cache.get_unit("test_key")
111
+
112
+ assert isinstance(unit_path, Path)
113
+ assert unit_path.suffix == ".pkl"
114
+ assert unit_path.parent == cache.path
115
+
116
+
117
+ def test_cache_get_unit_consistent():
118
+ """Test get_unit returns same path for same key"""
119
+ cache = Cache()
120
+
121
+ path1 = cache.get_unit("test_key")
122
+ path2 = cache.get_unit("test_key")
123
+
124
+ assert path1 == path2
125
+
126
+
127
+ def test_cache_get_unit_different_keys():
128
+ """Test get_unit returns different paths for different keys"""
129
+ cache = Cache()
130
+
131
+ path1 = cache.get_unit("key1")
132
+ path2 = cache.get_unit("key2")
133
+
134
+ assert path1 != path2
135
+
136
+
137
+ def test_cache_get_unit_uses_md5():
138
+ """Test get_unit uses MD5 hashing"""
139
+ cache = Cache()
140
+ unit_path = cache.get_unit("test_key")
141
+
142
+ # Verify it's a 32-character hex string (MD5)
143
+ assert len(unit_path.stem) == 32
144
+ int(unit_path.stem, 16)
145
+
146
+
147
+ def test_cache_get_unit_handles_special_characters():
148
+ """Test get_unit handles special characters in keys"""
149
+ cache = Cache()
150
+
151
+ path1 = cache.get_unit("key with spaces")
152
+ path2 = cache.get_unit("key/with/slashes")
153
+ path3 = cache.get_unit("键中文")
154
+
155
+ assert path1.exists() or not path1.exists() # Should not raise
156
+ assert path2.exists() or not path2.exists()
157
+ assert path3.exists() or not path3.exists()
158
+
159
+
160
+ # ==================== Contains Tests ====================
161
+
162
+
163
+ def test_cache_contains_false():
164
+ """Test __contains__ returns False for non-existent key"""
165
+ cache = Cache()
166
+
167
+ assert "nonexistent" not in cache
168
+
169
+
170
+ def test_cache_contains_true():
171
+ """Test __contains__ returns True for existing key"""
172
+ cache = Cache()
173
+ cache.set("test_key", "test_value")
174
+
175
+ assert "test_key" in cache
176
+
177
+
178
+ def test_cache_contains_after_delete():
179
+ """Test __contains__ returns False after deletion"""
180
+ cache = Cache()
181
+ cache.set("test_key", "test_value")
182
+
183
+ unit_path = cache.get_unit("test_key")
184
+ unit_path.unlink()
185
+
186
+ assert "test_key" not in cache
187
+
188
+
189
+ # ==================== String Representation Tests ====================
190
+
191
+
192
+ def test_cache_str():
193
+ """Test __str__ returns path string"""
194
+ cache = Cache()
195
+
196
+ str_repr = str(cache)
197
+
198
+ assert isinstance(str_repr, str)
199
+ assert str(cache.path) == str_repr
200
+
201
+
202
+ def test_cache_repr():
203
+ """Test __repr__ returns detailed representation"""
204
+ cache = Cache()
205
+
206
+ repr_str = repr(cache)
207
+
208
+ assert "Cache" in repr_str
209
+ assert "path=" in repr_str
210
+ assert str(cache.path) in repr_str
211
+
212
+
213
+ # ==================== Get Tests ====================
214
+
215
+
216
+ def test_cache_get_nonexistent():
217
+ """Test get returns None for non-existent key"""
218
+ cache = Cache()
219
+
220
+ result = cache.get("nonexistent")
221
+
222
+ assert result is None
223
+
224
+
225
+ def test_cache_get_existing():
226
+ """Test get returns value for existing key"""
227
+ cache = Cache()
228
+ cache.set("test_key", "test_value")
229
+
230
+ result = cache.get("test_key")
231
+
232
+ assert result == "test_value"
233
+
234
+
235
+ def test_cache_get_with_dict():
236
+ """Test get works with dictionary values"""
237
+ cache = Cache()
238
+ test_data = {"key": "value", "number": 42}
239
+ cache.set("dict_key", test_data)
240
+
241
+ result = cache.get("dict_key")
242
+
243
+ assert result == test_data
244
+ assert result["key"] == "value"
245
+ assert result["number"] == 42
246
+
247
+
248
+ def test_cache_get_with_list():
249
+ """Test get works with list values"""
250
+ cache = Cache()
251
+ test_data = [1, 2, 3, "four", {"five": 5}]
252
+ cache.set("list_key", test_data)
253
+
254
+ result = cache.get("list_key")
255
+
256
+ assert result == test_data
257
+
258
+
259
+ def test_cache_get_with_none_value():
260
+ """Test get works with None as value"""
261
+ cache = Cache()
262
+ cache.set("none_key", None)
263
+
264
+ result = cache.get("none_key")
265
+
266
+ # This is tricky - None value vs non-existent key
267
+ # Current implementation will return None for both
268
+ assert result is None
269
+
270
+
271
+ def test_cache_get_corrupted_file():
272
+ """Test get returns None for corrupted cache file"""
273
+ cache = Cache()
274
+ unit_path = cache.get_unit("corrupted")
275
+
276
+ # Create corrupted file
277
+ with unit_path.open("w") as f:
278
+ f.write("not valid pickle data")
279
+
280
+ result = cache.get("corrupted")
281
+
282
+ assert result is None
283
+
284
+
285
+ def test_cache_get_empty_file():
286
+ """Test get returns None for empty cache file"""
287
+ cache = Cache()
288
+ unit_path = cache.get_unit("empty")
289
+
290
+ # Create empty file
291
+ unit_path.touch()
292
+
293
+ result = cache.get("empty")
294
+
295
+ assert result is None
296
+
297
+
298
+ # ==================== Set Tests ====================
299
+
300
+
301
+ def test_cache_set_basic():
302
+ """Test set stores value"""
303
+ cache = Cache()
304
+
305
+ cache.set("test_key", "test_value")
306
+
307
+ unit_path = cache.get_unit("test_key")
308
+ assert unit_path.exists()
309
+
310
+
311
+ def test_cache_set_overwrites():
312
+ """Test set overwrites existing value"""
313
+ cache = Cache()
314
+
315
+ cache.set("test_key", "first_value")
316
+ cache.set("test_key", "second_value")
317
+
318
+ result = cache.get("test_key")
319
+ assert result == "second_value"
320
+
321
+
322
+ def test_cache_set_multiple_keys():
323
+ """Test set works with multiple keys"""
324
+ cache = Cache()
325
+
326
+ cache.set("key1", "value1")
327
+ cache.set("key2", "value2")
328
+ cache.set("key3", "value3")
329
+
330
+ assert cache.get("key1") == "value1"
331
+ assert cache.get("key2") == "value2"
332
+ assert cache.get("key3") == "value3"
333
+
334
+
335
+ def test_cache_set_complex_objects():
336
+ """Test set works with complex Python objects"""
337
+ cache = Cache()
338
+
339
+ test_data = {
340
+ "string": "text",
341
+ "number": 42,
342
+ "float": 3.14,
343
+ "list": [1, 2, 3],
344
+ "nested": {"inner": "value"},
345
+ "tuple": (1, 2, 3),
346
+ }
347
+
348
+ cache.set("complex", test_data)
349
+ result = cache.get("complex")
350
+
351
+ assert result == test_data
352
+
353
+
354
+ def test_cache_set_creates_pickle_file():
355
+ """Test set creates valid pickle file"""
356
+ cache = Cache()
357
+
358
+ cache.set("test_key", {"data": "value"})
359
+
360
+ unit_path = cache.get_unit("test_key")
361
+ with unit_path.open("rb") as f:
362
+ payload = pickle.load(f)
363
+
364
+ assert "value" in payload
365
+ assert payload["value"] == {"data": "value"}
366
+
367
+
368
+ # ==================== List Tests ====================
369
+
370
+
371
+ def test_cache_list_empty():
372
+ """Test list returns empty list for new cache"""
373
+ cache = Cache()
374
+
375
+ keys = cache.list()
376
+
377
+ assert isinstance(keys, list)
378
+ assert len(keys) == 0
379
+
380
+
381
+ def test_cache_list_with_items():
382
+ """Test list returns all cached keys"""
383
+ cache = Cache()
384
+
385
+ cache.set("key1", "value1")
386
+ cache.set("key2", "value2")
387
+ cache.set("key3", "value3")
388
+
389
+ keys = cache.list()
390
+
391
+ assert len(keys) == 3
392
+
393
+
394
+ def test_cache_list_returns_hashes():
395
+ """Test list returns MD5 hashes not original keys"""
396
+ cache = Cache()
397
+
398
+ cache.set("original_key", "value")
399
+
400
+ keys = cache.list()
401
+
402
+ assert len(keys) == 1
403
+ # Keys are MD5 hashes (32 hex chars)
404
+ assert len(keys[0]) == 32
405
+
406
+
407
+ def test_cache_list_after_clear():
408
+ """Test list returns empty after clear"""
409
+ cache = Cache()
410
+
411
+ cache.set("key1", "value1")
412
+ cache.set("key2", "value2")
413
+ cache.clear()
414
+
415
+ keys = cache.list()
416
+
417
+ assert len(keys) == 0
418
+
419
+
420
+ # ==================== Clear Tests ====================
421
+
422
+
423
+ def test_cache_clear_empty():
424
+ """Test clear on empty cache doesn't raise error"""
425
+ cache = Cache()
426
+
427
+ cache.clear() # Should not raise
428
+
429
+
430
+ def test_cache_clear_removes_files():
431
+ """Test clear removes all cache files"""
432
+ cache = Cache()
433
+
434
+ cache.set("key1", "value1")
435
+ cache.set("key2", "value2")
436
+
437
+ cache.clear()
438
+
439
+ assert len(list(cache.path.glob("*.pkl"))) == 0
440
+
441
+
442
+ def test_cache_clear_verifies_removal():
443
+ """Test clear actually removes accessible files"""
444
+ cache = Cache()
445
+
446
+ cache.set("key1", "value1")
447
+ cache.set("key2", "value2")
448
+
449
+ cache.clear()
450
+
451
+ assert cache.get("key1") is None
452
+ assert cache.get("key2") is None
453
+
454
+
455
+ def test_cache_clear_handles_errors():
456
+ """Test clear handles errors gracefully"""
457
+ cache = Cache()
458
+ cache.set("test", "value")
459
+
460
+ # Clear should not raise even if files can't be deleted
461
+ cache.clear() # Should complete without exception
462
+
463
+
464
+ # ==================== Describe / To Dict Tests ====================
465
+
466
+
467
+ def test_cache_describe():
468
+ """Test describe returns dict"""
469
+ cache = Cache()
470
+
471
+ result = cache.describe()
472
+
473
+ assert isinstance(result, dict)
474
+
475
+
476
+ def test_cache_describe_equals_to_dict():
477
+ """Test describe returns same as to_dict"""
478
+ cache = Cache()
479
+
480
+ describe_result = cache.describe()
481
+ to_dict_result = cache.to_dict()
482
+
483
+ assert describe_result == to_dict_result
484
+
485
+
486
+ def test_cache_to_dict_structure():
487
+ """Test to_dict returns expected structure"""
488
+ cache = Cache()
489
+
490
+ result = cache.to_dict()
491
+
492
+ assert "identifier" in result
493
+ assert "path" in result
494
+ assert "units" in result
495
+
496
+
497
+ def test_cache_to_dict_values():
498
+ """Test to_dict returns correct values"""
499
+ cache = Cache()
500
+
501
+ result = cache.to_dict()
502
+
503
+ assert result["identifier"] == cache.identifier
504
+ assert result["path"] == str(cache.path)
505
+ assert isinstance(result["units"], list)
506
+
507
+
508
+ def test_cache_to_dict_with_data():
509
+ """Test to_dict includes cache items"""
510
+ cache = Cache()
511
+
512
+ cache.set("key1", "value1")
513
+ cache.set("key2", "value2")
514
+
515
+ result = cache.to_dict()
516
+
517
+ assert len(result["units"]) == 2
518
+
519
+
520
+ # ==================== Integration Tests ====================
521
+
522
+
523
+ def test_cache_full_workflow():
524
+ """Test complete cache workflow"""
525
+ cache = Cache()
526
+
527
+ # Set values
528
+ cache.set("user", {"name": "张三", "age": 30})
529
+ cache.set("items", [1, 2, 3, 4, 5])
530
+
531
+ # Check existence
532
+ assert "user" in cache
533
+ assert "items" in cache
534
+ assert "nonexistent" not in cache
535
+
536
+ # Get values
537
+ user = cache.get("user")
538
+ items = cache.get("items")
539
+
540
+ assert user["name"] == "张三"
541
+ assert len(items) == 5
542
+
543
+ # List keys
544
+ keys = cache.list()
545
+ assert len(keys) == 2
546
+
547
+ # Get info
548
+ info = cache.to_dict()
549
+ assert len(info["units"]) == 2
550
+
551
+ # Clear
552
+ cache.clear()
553
+ assert len(cache.list()) == 0
554
+
555
+
556
+ def test_cache_persistence():
557
+ """Test cache persists across instances with same path"""
558
+ with tempfile.TemporaryDirectory() as tmpdir:
559
+ custom_path = Path(tmpdir)
560
+
561
+ # Create cache and set value
562
+ cache1 = Cache(path=custom_path)
563
+ identifier1 = cache1.identifier
564
+ cache1.set("persist_key", "persist_value")
565
+
566
+ # Create new cache with same base path
567
+ cache2 = Cache(path=custom_path / identifier1)
568
+ cache2.get("persist_key")
569
+
570
+ # Note: This won't work because each Cache gets unique identifier
571
+ # But the files exist in the directory
572
+ assert len(list((custom_path / identifier1).glob("*.pkl"))) > 0
573
+
574
+
575
+ def test_cache_isolation():
576
+ """Test different caches are isolated"""
577
+ cache1 = Cache()
578
+ cache2 = Cache()
579
+
580
+ cache1.set("key", "value1")
581
+ cache2.set("key", "value2")
582
+
583
+ assert cache1.get("key") == "value1"
584
+ assert cache2.get("key") == "value2"
585
+
586
+
587
+ def test_cache_handles_concurrent_operations():
588
+ """Test cache handles multiple operations in sequence"""
589
+ cache = Cache()
590
+
591
+ # Rapid set/get operations
592
+ for i in range(10):
593
+ cache.set(f"key{i}", f"value{i}")
594
+
595
+ # Verify all stored
596
+ for i in range(10):
597
+ assert cache.get(f"key{i}") == f"value{i}"
598
+
599
+ # List should have all
600
+ assert len(cache.list()) == 10
601
+
602
+
603
+ def test_cache_large_value():
604
+ """Test cache handles large values"""
605
+ cache = Cache()
606
+
607
+ # Large list
608
+ large_data = list(range(10000))
609
+ cache.set("large", large_data)
610
+
611
+ result = cache.get("large")
612
+
613
+ assert len(result) == 10000
614
+ assert result[0] == 0
615
+ assert result[-1] == 9999
616
+
617
+
618
+ def test_cache_unicode_keys():
619
+ """Test cache handles unicode in keys"""
620
+ cache = Cache()
621
+
622
+ cache.set("中文键", "中文值")
623
+ cache.set("🔑emoji", "😀emoji_value")
624
+
625
+ assert cache.get("中文键") == "中文值"
626
+ assert cache.get("🔑emoji") == "😀emoji_value"
627
+
628
+
629
+ def test_cache_update_value():
630
+ """Test updating cached value multiple times"""
631
+ cache = Cache()
632
+
633
+ cache.set("counter", 0)
634
+
635
+ for i in range(1, 6):
636
+ cache.set("counter", i)
637
+
638
+ result = cache.get("counter")
639
+ assert result == 5
640
+
641
+
642
+ def test_cache_binary_data():
643
+ """Test cache handles binary data"""
644
+ cache = Cache()
645
+
646
+ binary_data = b"\x00\x01\x02\x03\x04\x05"
647
+ cache.set("binary", binary_data)
648
+
649
+ result = cache.get("binary")
650
+ assert result == binary_data
651
+
652
+
653
+ def test_cache_nested_structures():
654
+ """Test cache handles deeply nested structures"""
655
+ cache = Cache()
656
+
657
+ nested = {"level1": {"level2": {"level3": {"level4": {"data": [1, 2, 3]}}}}}
658
+
659
+ cache.set("nested", nested)
660
+ result = cache.get("nested")
661
+
662
+ assert result["level1"]["level2"]["level3"]["level4"]["data"] == [1, 2, 3]
663
+
664
+
665
+ def test_cache_custom_path_cleanup():
666
+ """Test cache with custom path cleans up properly"""
667
+ with tempfile.TemporaryDirectory() as tmpdir:
668
+ custom_path = Path(tmpdir) / "test_cache"
669
+ cache = Cache(path=custom_path)
670
+
671
+ cache.set("key1", "value1")
672
+ cache.set("key2", "value2")
673
+
674
+ # Verify files created
675
+ assert len(list(cache.path.glob("*.pkl"))) == 2
676
+
677
+ # Clear
678
+ cache.clear()
679
+
680
+ # Verify files removed
681
+ assert len(list(cache.path.glob("*.pkl"))) == 0