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,692 @@
1
+ """
2
+ 描述:
3
+ - MacOSConnect 类的单元测试。
4
+ - 测试本地文件系统连接实现的所有功能和边界情况。
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import tempfile
10
+ from pathlib import Path
11
+
12
+ import pytest
13
+
14
+ from xfintech.connect.common.connect import ConnectLike
15
+ from xfintech.connect.common.connectref import ConnectRef
16
+ from xfintech.connect.common.error import ConnectFailedError, ConnectKeyError
17
+ from xfintech.connect.instance.macos import MacOSConnect
18
+
19
+ # =============================================================================
20
+ # Initialization Tests
21
+ # =============================================================================
22
+
23
+
24
+ def test_macosconnect_init():
25
+ """测试初始化"""
26
+ connect = MacOSConnect()
27
+ assert connect.kind == "macos"
28
+
29
+
30
+ def test_macosconnect_is_connectlike():
31
+ """测试 MacOSConnect 实现了 ConnectLike 协议"""
32
+ connect = MacOSConnect()
33
+ assert isinstance(connect, ConnectLike)
34
+
35
+
36
+ def test_macosconnect_has_docstring():
37
+ """测试 MacOSConnect 有文档字符串"""
38
+ assert MacOSConnect.__doc__ is not None
39
+ assert len(MacOSConnect.__doc__) > 0
40
+
41
+
42
+ # =============================================================================
43
+ # Path Resolution Tests
44
+ # =============================================================================
45
+
46
+
47
+ def test_resolve_path_with_string():
48
+ """测试用字符串解析路径"""
49
+ connect = MacOSConnect()
50
+ path = connect._resolve_path("/tmp/test.txt")
51
+
52
+ assert isinstance(path, Path)
53
+ # On macOS, /tmp resolves to /private/tmp
54
+ assert path.name == "test.txt"
55
+ assert path.is_absolute()
56
+
57
+
58
+ def test_resolve_path_with_path_object():
59
+ """测试用 Path 对象解析路径"""
60
+ connect = MacOSConnect()
61
+ input_path = Path("/tmp/test.txt")
62
+ path = connect._resolve_path(input_path)
63
+
64
+ assert isinstance(path, Path)
65
+ # After resolve(), paths may have different representations
66
+ assert path.name == "test.txt"
67
+ assert path.is_absolute()
68
+
69
+
70
+ def test_resolve_path_with_tilde():
71
+ """测试展开波浪号"""
72
+ connect = MacOSConnect()
73
+ path = connect._resolve_path("~/test.txt")
74
+
75
+ assert not str(path).startswith("~")
76
+ assert path.is_absolute()
77
+
78
+
79
+ def test_resolve_path_with_relative():
80
+ """测试相对路径转换为绝对路径"""
81
+ connect = MacOSConnect()
82
+ path = connect._resolve_path("test.txt")
83
+
84
+ assert path.is_absolute()
85
+
86
+
87
+ def test_resolve_path_none_raises_error():
88
+ """测试 None 路径抛出错误"""
89
+ connect = MacOSConnect()
90
+
91
+ with pytest.raises(ConnectKeyError) as excinfo:
92
+ connect._resolve_path(None)
93
+ assert "location cannot be None" in str(excinfo.value)
94
+
95
+
96
+ # =============================================================================
97
+ # put_bytes Tests
98
+ # =============================================================================
99
+
100
+
101
+ def test_put_bytes_creates_file():
102
+ """测试创建文件"""
103
+ with tempfile.TemporaryDirectory() as tmpdir:
104
+ connect = MacOSConnect()
105
+ file_path = Path(tmpdir) / "test.txt"
106
+
107
+ connect.put_bytes(b"test data", str(file_path))
108
+
109
+ assert file_path.exists()
110
+ assert file_path.read_bytes() == b"test data"
111
+
112
+
113
+ def test_put_bytes_creates_parent_directories():
114
+ """测试创建父目录"""
115
+ with tempfile.TemporaryDirectory() as tmpdir:
116
+ connect = MacOSConnect()
117
+ file_path = Path(tmpdir) / "subdir1" / "subdir2" / "test.txt"
118
+
119
+ connect.put_bytes(b"data", str(file_path))
120
+
121
+ assert file_path.exists()
122
+ assert file_path.parent.exists()
123
+
124
+
125
+ def test_put_bytes_overwrites_existing():
126
+ """测试覆盖现有文件"""
127
+ with tempfile.TemporaryDirectory() as tmpdir:
128
+ connect = MacOSConnect()
129
+ file_path = Path(tmpdir) / "test.txt"
130
+
131
+ # Write first time
132
+ connect.put_bytes(b"original", str(file_path))
133
+ assert file_path.read_bytes() == b"original"
134
+
135
+ # Overwrite
136
+ connect.put_bytes(b"updated", str(file_path))
137
+ assert file_path.read_bytes() == b"updated"
138
+
139
+
140
+ def test_put_bytes_with_path_object():
141
+ """测试使用 Path 对象写入"""
142
+ with tempfile.TemporaryDirectory() as tmpdir:
143
+ connect = MacOSConnect()
144
+ file_path = Path(tmpdir) / "test.txt"
145
+
146
+ connect.put_bytes(b"data", file_path)
147
+
148
+ assert file_path.read_bytes() == b"data"
149
+
150
+
151
+ def test_put_bytes_empty_data():
152
+ """测试写入空数据"""
153
+ with tempfile.TemporaryDirectory() as tmpdir:
154
+ connect = MacOSConnect()
155
+ file_path = Path(tmpdir) / "empty.txt"
156
+
157
+ connect.put_bytes(b"", str(file_path))
158
+
159
+ assert file_path.exists()
160
+ assert file_path.read_bytes() == b""
161
+
162
+
163
+ def test_put_bytes_large_data():
164
+ """测试写入大数据"""
165
+ with tempfile.TemporaryDirectory() as tmpdir:
166
+ connect = MacOSConnect()
167
+ file_path = Path(tmpdir) / "large.bin"
168
+ large_data = b"x" * (10 * 1024 * 1024) # 10MB
169
+
170
+ connect.put_bytes(large_data, str(file_path))
171
+
172
+ assert file_path.read_bytes() == large_data
173
+
174
+
175
+ def test_put_bytes_with_tilde():
176
+ """测试使用波浪号路径"""
177
+ # Use a temp directory inside the home directory to avoid polluting actual home
178
+ with tempfile.TemporaryDirectory() as tmpdir:
179
+ connect = MacOSConnect()
180
+ # Create a file with absolute path, test that tilde expansion would work
181
+ file_path = Path(tmpdir) / "test.txt"
182
+
183
+ connect.put_bytes(b"data", str(file_path))
184
+ assert file_path.exists()
185
+
186
+
187
+ def test_put_bytes_none_location():
188
+ """测试 None 位置"""
189
+ connect = MacOSConnect()
190
+
191
+ with pytest.raises(ConnectKeyError) as excinfo:
192
+ connect.put_bytes(b"data", None)
193
+ assert "location cannot be None" in str(excinfo.value)
194
+
195
+
196
+ def test_put_bytes_invalid_path():
197
+ """测试写入无效路径"""
198
+ connect = MacOSConnect()
199
+
200
+ # Test with a file that exists as a directory
201
+ with tempfile.TemporaryDirectory() as tmpdir:
202
+ # Try to write to a path that's actually a directory
203
+ dir_path = Path(tmpdir) / "existing_dir"
204
+ dir_path.mkdir()
205
+
206
+ with pytest.raises(ConnectFailedError):
207
+ connect.put_bytes(b"data", dir_path)
208
+
209
+
210
+ # =============================================================================
211
+ # get_bytes Tests
212
+ # =============================================================================
213
+
214
+
215
+ def test_get_bytes_reads_file():
216
+ """测试读取文件"""
217
+ with tempfile.TemporaryDirectory() as tmpdir:
218
+ connect = MacOSConnect()
219
+ file_path = Path(tmpdir) / "test.txt"
220
+ file_path.write_bytes(b"test data")
221
+
222
+ data = connect.get_bytes(str(file_path))
223
+
224
+ assert data == b"test data"
225
+
226
+
227
+ def test_get_bytes_with_path_object():
228
+ """测试使用 Path 对象读取"""
229
+ with tempfile.TemporaryDirectory() as tmpdir:
230
+ connect = MacOSConnect()
231
+ file_path = Path(tmpdir) / "test.txt"
232
+ file_path.write_bytes(b"data")
233
+
234
+ data = connect.get_bytes(file_path)
235
+
236
+ assert data == b"data"
237
+
238
+
239
+ def test_get_bytes_empty_file():
240
+ """测试读取空文件"""
241
+ with tempfile.TemporaryDirectory() as tmpdir:
242
+ connect = MacOSConnect()
243
+ file_path = Path(tmpdir) / "empty.txt"
244
+ file_path.write_bytes(b"")
245
+
246
+ data = connect.get_bytes(str(file_path))
247
+
248
+ assert data == b""
249
+
250
+
251
+ def test_get_bytes_large_file():
252
+ """测试读取大文件"""
253
+ with tempfile.TemporaryDirectory() as tmpdir:
254
+ connect = MacOSConnect()
255
+ file_path = Path(tmpdir) / "large.bin"
256
+ large_data = b"x" * (10 * 1024 * 1024) # 10MB
257
+ file_path.write_bytes(large_data)
258
+
259
+ data = connect.get_bytes(str(file_path))
260
+
261
+ assert data == large_data
262
+
263
+
264
+ def test_get_bytes_with_tilde():
265
+ """测试使用波浪号路径读取"""
266
+ with tempfile.TemporaryDirectory() as tmpdir:
267
+ connect = MacOSConnect()
268
+ file_path = Path(tmpdir) / "test.txt"
269
+ file_path.write_bytes(b"data")
270
+
271
+ data = connect.get_bytes(str(file_path))
272
+ assert data == b"data"
273
+
274
+
275
+ def test_get_bytes_none_location():
276
+ """测试 None 位置"""
277
+ connect = MacOSConnect()
278
+
279
+ with pytest.raises(ConnectKeyError) as excinfo:
280
+ connect.get_bytes(None)
281
+ assert "location cannot be None" in str(excinfo.value)
282
+
283
+
284
+ def test_get_bytes_nonexistent_file():
285
+ """测试读取不存在的文件"""
286
+ with tempfile.TemporaryDirectory() as tmpdir:
287
+ connect = MacOSConnect()
288
+ nonexistent = Path(tmpdir) / "subdir" / "nonexistent.txt"
289
+
290
+ # File doesn't exist, but directory will be created by _resolve_path
291
+ # The error happens when trying to open the file
292
+ with pytest.raises(ConnectFailedError) as excinfo:
293
+ connect.get_bytes(str(nonexistent))
294
+ assert "no such file" in str(excinfo.value).lower()
295
+
296
+
297
+ def test_get_bytes_directory():
298
+ """测试读取目录"""
299
+ with tempfile.TemporaryDirectory() as tmpdir:
300
+ connect = MacOSConnect()
301
+
302
+ with pytest.raises(ConnectFailedError) as excinfo:
303
+ connect.get_bytes(tmpdir)
304
+ # Error message is "Is a directory"
305
+ assert "directory" in str(excinfo.value).lower()
306
+
307
+
308
+ # =============================================================================
309
+ # put_object Tests
310
+ # =============================================================================
311
+
312
+
313
+ def test_put_object_returns_connectref():
314
+ """测试 put_object 返回 ConnectRef"""
315
+ with tempfile.TemporaryDirectory() as tmpdir:
316
+ connect = MacOSConnect()
317
+ file_path = Path(tmpdir) / "test.txt"
318
+
319
+ ref = connect.put_object(b"data", str(file_path))
320
+
321
+ assert isinstance(ref, ConnectRef)
322
+ assert ref.kind == "macos"
323
+ assert str(file_path) in ref.location
324
+
325
+
326
+ def test_put_object_writes_file():
327
+ """测试 put_object 写入文件"""
328
+ with tempfile.TemporaryDirectory() as tmpdir:
329
+ connect = MacOSConnect()
330
+ file_path = Path(tmpdir) / "test.txt"
331
+
332
+ connect.put_object(b"test data", str(file_path))
333
+
334
+ assert file_path.exists()
335
+ assert file_path.read_bytes() == b"test data"
336
+
337
+
338
+ def test_put_object_with_path_object():
339
+ """测试使用 Path 对象"""
340
+ with tempfile.TemporaryDirectory() as tmpdir:
341
+ connect = MacOSConnect()
342
+ file_path = Path(tmpdir) / "test.txt"
343
+
344
+ connect.put_object(b"data", file_path)
345
+
346
+ assert file_path.read_bytes() == b"data"
347
+
348
+
349
+ def test_put_object_none_location():
350
+ """测试 None 位置"""
351
+ connect = MacOSConnect()
352
+
353
+ with pytest.raises(ConnectKeyError):
354
+ connect.put_object(b"data", None)
355
+
356
+
357
+ # =============================================================================
358
+ # get_object Tests
359
+ # =============================================================================
360
+
361
+
362
+ def test_get_object_returns_bytes():
363
+ """测试 get_object 返回字节"""
364
+ with tempfile.TemporaryDirectory() as tmpdir:
365
+ connect = MacOSConnect()
366
+ file_path = Path(tmpdir) / "test.txt"
367
+ file_path.write_bytes(b"test data")
368
+
369
+ data = connect.get_object(str(file_path))
370
+
371
+ assert isinstance(data, bytes)
372
+ assert data == b"test data"
373
+
374
+
375
+ def test_get_object_reads_file():
376
+ """测试 get_object 读取文件"""
377
+ with tempfile.TemporaryDirectory() as tmpdir:
378
+ connect = MacOSConnect()
379
+ file_path = Path(tmpdir) / "test.txt"
380
+ file_path.write_bytes(b"data")
381
+
382
+ data = connect.get_object(str(file_path))
383
+
384
+ assert data == b"data"
385
+
386
+
387
+ def test_get_object_with_path_object():
388
+ """测试使用 Path 对象"""
389
+ with tempfile.TemporaryDirectory() as tmpdir:
390
+ connect = MacOSConnect()
391
+ file_path = Path(tmpdir) / "test.txt"
392
+ file_path.write_bytes(b"data")
393
+
394
+ data = connect.get_object(file_path)
395
+
396
+ assert data == b"data"
397
+
398
+
399
+ def test_get_object_none_location():
400
+ """测试 None 位置"""
401
+ connect = MacOSConnect()
402
+
403
+ with pytest.raises(ConnectKeyError):
404
+ connect.get_object(None)
405
+
406
+
407
+ def test_get_object_nonexistent():
408
+ """测试读取不存在的文件"""
409
+ with tempfile.TemporaryDirectory() as tmpdir:
410
+ connect = MacOSConnect()
411
+ nonexistent = Path(tmpdir) / "subdir" / "nonexistent.txt"
412
+
413
+ with pytest.raises(ConnectFailedError):
414
+ connect.get_object(str(nonexistent))
415
+
416
+
417
+ # =============================================================================
418
+ # Integration Tests
419
+ # =============================================================================
420
+
421
+
422
+ def test_round_trip():
423
+ """测试完整的读写流程"""
424
+ with tempfile.TemporaryDirectory() as tmpdir:
425
+ connect = MacOSConnect()
426
+ file_path = Path(tmpdir) / "test.txt"
427
+
428
+ # Write
429
+ ref = connect.put_object(b"test data", str(file_path))
430
+ assert ref.kind == "macos"
431
+
432
+ # Read
433
+ data = connect.get_object(str(file_path))
434
+ assert data == b"test data"
435
+
436
+
437
+ def test_multiple_files():
438
+ """测试多个文件操作"""
439
+ with tempfile.TemporaryDirectory() as tmpdir:
440
+ connect = MacOSConnect()
441
+
442
+ files = {
443
+ "file1.txt": b"data1",
444
+ "file2.txt": b"data2",
445
+ "file3.txt": b"data3",
446
+ }
447
+
448
+ # Write all files
449
+ for filename, data in files.items():
450
+ file_path = Path(tmpdir) / filename
451
+ connect.put_object(data, str(file_path))
452
+
453
+ # Read and verify
454
+ for filename, expected_data in files.items():
455
+ file_path = Path(tmpdir) / filename
456
+ actual_data = connect.get_object(str(file_path))
457
+ assert actual_data == expected_data
458
+
459
+
460
+ def test_nested_directories():
461
+ """测试嵌套目录"""
462
+ with tempfile.TemporaryDirectory() as tmpdir:
463
+ connect = MacOSConnect()
464
+
465
+ nested_path = Path(tmpdir) / "level1" / "level2" / "level3" / "file.txt"
466
+
467
+ # Write creates all directories
468
+ connect.put_object(b"nested data", str(nested_path))
469
+
470
+ # Read works
471
+ data = connect.get_object(str(nested_path))
472
+ assert data == b"nested data"
473
+
474
+
475
+ def test_update_file():
476
+ """测试更新文件"""
477
+ with tempfile.TemporaryDirectory() as tmpdir:
478
+ connect = MacOSConnect()
479
+ file_path = Path(tmpdir) / "update.txt"
480
+
481
+ # Initial write
482
+ connect.put_object(b"version 1", str(file_path))
483
+ assert connect.get_object(str(file_path)) == b"version 1"
484
+
485
+ # Update
486
+ connect.put_object(b"version 2", str(file_path))
487
+ assert connect.get_object(str(file_path)) == b"version 2"
488
+
489
+
490
+ # =============================================================================
491
+ # Edge Cases
492
+ # =============================================================================
493
+
494
+
495
+ def test_unicode_filename():
496
+ """测试 Unicode 文件名"""
497
+ with tempfile.TemporaryDirectory() as tmpdir:
498
+ connect = MacOSConnect()
499
+ file_path = Path(tmpdir) / "测试文件.txt"
500
+
501
+ connect.put_object(b"unicode data", str(file_path))
502
+ data = connect.get_object(str(file_path))
503
+
504
+ assert data == b"unicode data"
505
+
506
+
507
+ def test_special_characters_filename():
508
+ """测试特殊字符文件名"""
509
+ with tempfile.TemporaryDirectory() as tmpdir:
510
+ connect = MacOSConnect()
511
+ file_path = Path(tmpdir) / "file with spaces & special!.txt"
512
+
513
+ connect.put_object(b"special", str(file_path))
514
+ data = connect.get_object(str(file_path))
515
+
516
+ assert data == b"special"
517
+
518
+
519
+ def test_very_long_path():
520
+ """测试很长的路径"""
521
+ with tempfile.TemporaryDirectory() as tmpdir:
522
+ connect = MacOSConnect()
523
+
524
+ # Create a path with many nested directories
525
+ long_path = Path(tmpdir)
526
+ for i in range(10):
527
+ long_path = long_path / f"directory_{i}"
528
+ long_path = long_path / "file.txt"
529
+
530
+ connect.put_object(b"deep data", str(long_path))
531
+ data = connect.get_object(str(long_path))
532
+
533
+ assert data == b"deep data"
534
+
535
+
536
+ def test_binary_data():
537
+ """测试二进制数据"""
538
+ with tempfile.TemporaryDirectory() as tmpdir:
539
+ connect = MacOSConnect()
540
+ file_path = Path(tmpdir) / "binary.bin"
541
+
542
+ # Create binary data with all byte values
543
+ binary_data = bytes(range(256))
544
+
545
+ connect.put_object(binary_data, str(file_path))
546
+ data = connect.get_object(str(file_path))
547
+
548
+ assert data == binary_data
549
+
550
+
551
+ def test_concurrent_writes():
552
+ """测试并发写入不同文件"""
553
+ with tempfile.TemporaryDirectory() as tmpdir:
554
+ connect = MacOSConnect()
555
+
556
+ # Simulate multiple sequential writes (can't truly test concurrency here)
557
+ for i in range(10):
558
+ file_path = Path(tmpdir) / f"file_{i}.txt"
559
+ connect.put_object(f"data_{i}".encode(), str(file_path))
560
+
561
+ # Verify all files
562
+ for i in range(10):
563
+ file_path = Path(tmpdir) / f"file_{i}.txt"
564
+ data = connect.get_object(str(file_path))
565
+ assert data == f"data_{i}".encode()
566
+
567
+
568
+ # =============================================================================
569
+ # Type Tests
570
+ # =============================================================================
571
+
572
+
573
+ def test_returns_correct_types():
574
+ """测试返回正确的类型"""
575
+ with tempfile.TemporaryDirectory() as tmpdir:
576
+ connect = MacOSConnect()
577
+ file_path = Path(tmpdir) / "test.txt"
578
+
579
+ # put_object returns ConnectRef
580
+ ref = connect.put_object(b"data", str(file_path))
581
+ assert isinstance(ref, ConnectRef)
582
+
583
+ # get_object returns bytes
584
+ data = connect.get_object(str(file_path))
585
+ assert isinstance(data, bytes)
586
+
587
+ # put_bytes returns None
588
+ result = connect.put_bytes(b"data", str(file_path))
589
+ assert result is None
590
+
591
+ # get_bytes returns bytes
592
+ data = connect.get_bytes(str(file_path))
593
+ assert isinstance(data, bytes)
594
+
595
+
596
+ def test_connectref_has_correct_attributes():
597
+ """测试 ConnectRef 有正确的属性"""
598
+ with tempfile.TemporaryDirectory() as tmpdir:
599
+ connect = MacOSConnect()
600
+ file_path = Path(tmpdir) / "test.txt"
601
+
602
+ ref = connect.put_object(b"data", str(file_path))
603
+
604
+ assert hasattr(ref, "location")
605
+ assert hasattr(ref, "kind")
606
+ assert ref.kind == "macos"
607
+ assert str(file_path) in ref.location
608
+
609
+
610
+ # =============================================================================
611
+ # Error Message Tests
612
+ # =============================================================================
613
+
614
+
615
+ def test_connectkeyerror_message():
616
+ """测试 ConnectKeyError 错误消息"""
617
+ connect = MacOSConnect()
618
+
619
+ try:
620
+ connect.put_bytes(b"data", None)
621
+ except ConnectKeyError as e:
622
+ assert "location cannot be None" in str(e)
623
+
624
+
625
+ def test_connectfailederror_message_read():
626
+ """测试读取失败的错误消息"""
627
+ with tempfile.TemporaryDirectory() as tmpdir:
628
+ connect = MacOSConnect()
629
+ nonexistent = Path(tmpdir) / "subdir" / "nonexistent.txt"
630
+
631
+ try:
632
+ connect.get_bytes(str(nonexistent))
633
+ except ConnectFailedError as e:
634
+ assert "no such file" in str(e).lower()
635
+
636
+
637
+ def test_connectfailederror_message_write():
638
+ """测试写入失败的错误消息"""
639
+ with tempfile.TemporaryDirectory() as tmpdir:
640
+ connect = MacOSConnect()
641
+ # Try to write to a directory (not a file)
642
+ dir_path = Path(tmpdir) / "existing_dir"
643
+ dir_path.mkdir()
644
+
645
+ try:
646
+ connect.put_bytes(b"data", dir_path)
647
+ except ConnectFailedError as e:
648
+ assert "directory" in str(e).lower() or "is a" in str(e).lower()
649
+
650
+
651
+ # =============================================================================
652
+ # Compatibility Tests
653
+ # =============================================================================
654
+
655
+
656
+ def test_works_with_string_path():
657
+ """测试与字符串路径兼容"""
658
+ with tempfile.TemporaryDirectory() as tmpdir:
659
+ connect = MacOSConnect()
660
+ file_path = str(Path(tmpdir) / "test.txt")
661
+
662
+ connect.put_object(b"data", file_path)
663
+ data = connect.get_object(file_path)
664
+
665
+ assert data == b"data"
666
+
667
+
668
+ def test_works_with_pathlib_path():
669
+ """测试与 pathlib.Path 兼容"""
670
+ with tempfile.TemporaryDirectory() as tmpdir:
671
+ connect = MacOSConnect()
672
+ file_path = Path(tmpdir) / "test.txt"
673
+
674
+ connect.put_object(b"data", file_path)
675
+ data = connect.get_object(file_path)
676
+
677
+ assert data == b"data"
678
+
679
+
680
+ def test_mixed_path_types():
681
+ """测试混合使用路径类型"""
682
+ with tempfile.TemporaryDirectory() as tmpdir:
683
+ connect = MacOSConnect()
684
+ file_path = Path(tmpdir) / "test.txt"
685
+
686
+ # Write with Path object
687
+ connect.put_object(b"data", file_path)
688
+
689
+ # Read with string
690
+ data = connect.get_object(str(file_path))
691
+
692
+ assert data == b"data"