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,17 @@
1
+ from xfintech.data.job.errors import (
2
+ JobAlreadyRegisteredError,
3
+ JobNameError,
4
+ JobNotFoundError,
5
+ )
6
+ from xfintech.data.job.house import House
7
+ from xfintech.data.job.joblike import JobLike
8
+
9
+ JobHouse = House() # 创建一个全局的 JobHouse 实例
10
+
11
+ __all__ = [
12
+ "JobNotFoundError",
13
+ "JobAlreadyRegisteredError",
14
+ "JobNameError",
15
+ "JobHouse",
16
+ "JobLike",
17
+ ]
@@ -0,0 +1,112 @@
1
+ from __future__ import annotations
2
+
3
+
4
+ class JobNotFoundError(KeyError):
5
+ """
6
+ 描述:
7
+ - Job 未找到异常,当尝试查找不存在的 Job 名称或别名时抛出。
8
+ - 继承自 KeyError,表示键查找失败。
9
+
10
+ 参数:
11
+ - message: str, 错误信息,通常包含未找到的 Job 名称。
12
+
13
+ 方法:
14
+ - 继承自 KeyError 的所有方法。
15
+
16
+ 例子:
17
+ ```python
18
+ from xfintech.data.job.house import House
19
+ from xfintech.data.job.errors import JobNotFoundError
20
+
21
+ house = House()
22
+
23
+ try:
24
+ house.lookup("nonexistent_job")
25
+ except JobNotFoundError as e:
26
+ print(f"Error: {e}") # Error: job not found: nonexistent_job
27
+ ```
28
+ """
29
+
30
+ pass
31
+
32
+
33
+ class JobAlreadyRegisteredError(KeyError):
34
+ """
35
+ 描述:
36
+ - Job 已注册异常,当尝试注册已存在的 Job 名称或别名时抛出(replace=False)。
37
+ - 继承自 KeyError,表示键冲突。
38
+
39
+ 参数:
40
+ - message: str, 错误信息,通常包含冲突的 Job 名称或别名。
41
+
42
+ 方法:
43
+ - 继承自 KeyError 的所有方法。
44
+
45
+ 例子:
46
+ ```python
47
+ from xfintech.data.job.house import House
48
+ from xfintech.data.job.errors import JobAlreadyRegisteredError
49
+
50
+ house = House()
51
+
52
+ @house.register("my_job")
53
+ class MyJob:
54
+ pass
55
+
56
+ # 尝试重复注册会抛出异常
57
+ try:
58
+ @house.register("my_job")
59
+ class AnotherJob:
60
+ pass
61
+ except JobAlreadyRegisteredError as e:
62
+ print(f"Error: {e}") # Error: Job already registered: my_job
63
+
64
+ # 使用 replace=True 可以覆盖
65
+ @house.register("my_job", replace=True)
66
+ class ReplacedJob:
67
+ pass
68
+ ```
69
+ """
70
+
71
+ pass
72
+
73
+
74
+ class JobNameError(ValueError):
75
+ """
76
+ 描述:
77
+ - Job 名称错误异常,当提供的 Job 名称格式不正确时抛出。
78
+ - 继承自 ValueError,表示值不合法。
79
+ - 名称必须是非空字符串。
80
+
81
+ 参数:
82
+ - message: str, 错误信息,描述名称错误的原因。
83
+
84
+ 方法:
85
+ - 继承自 ValueError 的所有方法。
86
+
87
+ 例子:
88
+ ```python
89
+ from xfintech.data.job.house import House
90
+ from xfintech.data.job.errors import JobNameError
91
+
92
+ house = House()
93
+
94
+ # 空字符串名称会抛出异常
95
+ try:
96
+ @house.register("")
97
+ class MyJob:
98
+ pass
99
+ except JobNameError as e:
100
+ print(f"Error: {e}") # Error: job name cannot be empty
101
+
102
+ # 非字符串类型会抛出异常
103
+ try:
104
+ @house.register(123)
105
+ class MyJob:
106
+ pass
107
+ except JobNameError as e:
108
+ print(f"Error: {e}") # Error: job name must be str, got <class 'int'>
109
+ ```
110
+ """
111
+
112
+ pass
@@ -0,0 +1,156 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from xfintech.data.job.errors import (
6
+ JobAlreadyRegisteredError,
7
+ JobNameError,
8
+ JobNotFoundError,
9
+ )
10
+
11
+
12
+ class House:
13
+ """
14
+ 描述:
15
+ - Job 注册和管理容器,提供 Job 类的注册、查找和创建功能。
16
+ - 支持 Job 别名机制,允许一个 Job 类有多个访问名称。
17
+ - 所有名称不区分大小写,自动归一化处理。
18
+ - 提供装饰器模式注册 Job 类。
19
+
20
+ 参数:
21
+ - 无参数。
22
+
23
+ 属性:
24
+ - _jobs: dict[str, type], Job 名称到类的映射字典。
25
+ - _aliases: dict[str, str], 别名到 Job 名称的映射字典。
26
+
27
+ 方法:
28
+ - register(name, alias=None, replace=False): 装饰器方法,注册 Job 类。
29
+ - lookup(name): 根据名称或别名查找 Job 类。
30
+ - create(name, *args, **kwargs): 根据名称创建 Job 实例。
31
+ - list(): 返回所有已注册的 Job 名称列表。
32
+
33
+ 例子:
34
+ ```python
35
+ from xfintech.data.job.house import House
36
+
37
+ # 创建 House 实例
38
+ house = House()
39
+
40
+ # 使用装饰器注册 Job
41
+ @house.register("stock_daily", alias="daily")
42
+ class StockDailyJob:
43
+ def __init__(self, symbol):
44
+ self.symbol = symbol
45
+
46
+ def run(self):
47
+ return f"Running daily job for {self.symbol}"
48
+
49
+ # 查找 Job 类
50
+ JobClass = house.lookup("stock_daily")
51
+ print(JobClass) # <class 'StockDailyJob'>
52
+
53
+ # 通过别名查找
54
+ JobClass = house.lookup("daily")
55
+ print(JobClass) # <class 'StockDailyJob'>
56
+
57
+ # 创建 Job 实例
58
+ job = house.create("stock_daily", symbol="AAPL")
59
+ print(job.run()) # Running daily job for AAPL
60
+
61
+ # 通过别名创建
62
+ job = house.create("daily", symbol="TSLA")
63
+ print(job.run()) # Running daily job for TSLA
64
+
65
+ # 列出所有注册的 Job
66
+ jobs = house.list()
67
+ print(jobs) # ['stock_daily']
68
+
69
+ # 名称不区分大小写
70
+ JobClass = house.lookup("STOCK_DAILY")
71
+ JobClass = house.lookup("Stock_Daily")
72
+
73
+ # 替换已注册的 Job
74
+ @house.register("stock_daily", replace=True)
75
+ class NewStockDailyJob:
76
+ pass
77
+
78
+ # 错误处理示例
79
+ from xfintech.data.job.errors import JobNotFoundError
80
+ try:
81
+ house.lookup("nonexistent")
82
+ except JobNotFoundError as e:
83
+ print(f"Error: {e}") # Error: job not found: nonexistent
84
+ ```
85
+ """
86
+
87
+ def __init__(self) -> None:
88
+ self._jobs: dict[str, type] = {}
89
+ self._aliases: dict[str, str] = {}
90
+
91
+ @staticmethod
92
+ def _normalize_name(
93
+ name: str,
94
+ ) -> str:
95
+ if not isinstance(name, str):
96
+ raise JobNameError(f"job name must be str, got {type(name)}")
97
+ key = name.strip().lower()
98
+ if not key:
99
+ raise JobNameError("job name cannot be empty")
100
+ return key
101
+
102
+ def register(
103
+ self,
104
+ name: str,
105
+ alias: str | None = None,
106
+ replace: bool = False,
107
+ strict: bool = False,
108
+ ):
109
+ namekey = self._normalize_name(name)
110
+
111
+ def deco(cls):
112
+ name_in_use = namekey in self._jobs
113
+ if (not replace) and (name_in_use):
114
+ if strict:
115
+ msg = f"Job already registered: {namekey}"
116
+ raise JobAlreadyRegisteredError(msg)
117
+ else:
118
+ self._jobs[namekey] = cls
119
+
120
+ if alias is not None:
121
+ aliaskey = self._normalize_name(alias)
122
+ aliaskey_in_use = aliaskey in self._aliases
123
+ if (not replace) and (aliaskey_in_use) and (self._aliases[aliaskey] != namekey):
124
+ msg = f"Alias already used: {aliaskey}"
125
+ raise JobAlreadyRegisteredError(msg)
126
+ self._aliases[aliaskey] = namekey
127
+
128
+ cls.__job_name__ = namekey
129
+ return cls
130
+
131
+ return deco
132
+
133
+ def lookup(
134
+ self,
135
+ name: str,
136
+ ) -> type:
137
+ key = self._normalize_name(name)
138
+ if key in self._jobs:
139
+ return self._jobs[key]
140
+ if key in self._aliases:
141
+ return self._jobs[self._aliases[key]]
142
+ raise JobNotFoundError(f"job not found: {name}")
143
+
144
+ def create(
145
+ self,
146
+ name: str,
147
+ *args,
148
+ **kwargs,
149
+ ) -> Any:
150
+ return self.lookup(name)(*args, **kwargs)
151
+
152
+ def list(self) -> list[str]:
153
+ keys = self._jobs.keys()
154
+ aliases = self._aliases.keys()
155
+ items = list(keys) + list(aliases)
156
+ return sorted(set(items))
@@ -0,0 +1,247 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Dict, Optional
4
+
5
+ from xfintech.data.common.cache import Cache
6
+ from xfintech.data.common.coolant import Coolant
7
+ from xfintech.data.common.metric import Metric
8
+ from xfintech.data.common.paginate import Paginate
9
+ from xfintech.data.common.params import Params
10
+ from xfintech.data.common.retry import Retry
11
+ from xfintech.data.job.joblike import JobLike
12
+ from xfintech.fabric.table.info import TableInfo
13
+
14
+
15
+ class Job(JobLike):
16
+ """
17
+ 描述:
18
+ - 作业基类,用于管理数据请求任务的执行、重试、缓存和监控。
19
+ - 集成参数管理、分页、冷却、重试、缓存和性能度量等功能。
20
+ - 提供完整的作业生命周期管理,包括初始化、执行、重置等。
21
+ - 子类需实现 _run() 方法来定义具体的执行逻辑。
22
+
23
+ 属性:
24
+ - name: str, 作业名称。
25
+ - key: str, 作业唯一标识键。
26
+ - source: Optional[TableInfo], 数据源表信息。
27
+ - target: Optional[TableInfo], 目标表信息。
28
+ - params: Params, 作业参数对象。
29
+ - coolant: Coolant, 冷却控制对象,用于速率限制。
30
+ - paginate: Paginate, 分页管理对象。
31
+ - retry: Retry, 重试策略对象。
32
+ - cache: Optional[Cache], 缓存管理对象。
33
+ - metric: Metric, 性能度量对象,记录执行时间和错误。
34
+
35
+ 方法:
36
+ - run(): 执行作业,包含重试逻辑和性能度量。
37
+ - _run(): 抽象方法,子类必须实现具体的执行逻辑。
38
+ - markpoint(name): 在 metric 中标记检查点。
39
+ - cool(): 执行冷却等待。
40
+ - get_params(): 获取作业参数字典。
41
+ - get_cache(unit): 从缓存获取数据。
42
+ - set_cache(unit, data): 将数据保存到缓存。
43
+ - reset(): 重置 metric 和清空缓存。
44
+ - describe(): 返回作业描述信息(不包含敏感数据)。
45
+ - to_dict(): 返回作业完整信息字典。
46
+
47
+ 例子:
48
+ ```python
49
+ from xfintech.data.job.job import Job
50
+ from xfintech.data.common.params import Params
51
+
52
+ # 创建自定义作业
53
+ class MyDataJob(Job):
54
+ def _run(self):
55
+ # 实现具体的数据获取逻辑
56
+ data = fetch_data(self.params)
57
+ return data
58
+
59
+ # 使用作业
60
+ job = MyDataJob(
61
+ name="daily_data",
62
+ key="daily_data_001",
63
+ params={"symbol": "AAPL", "date": "20240115"},
64
+ retry={"max_retries": 3, "interval": 5},
65
+ cache=True # 启用缓存
66
+ )
67
+
68
+ # 执行作业
69
+ result = job.run()
70
+
71
+ # 查看执行信息
72
+ print(f"执行耗时: {job.metric.duration} 秒")
73
+ print(job.describe())
74
+ ```
75
+ """
76
+
77
+ def __init__(
78
+ self,
79
+ name: str,
80
+ key: str,
81
+ source: Optional[TableInfo] = None,
82
+ target: Optional[TableInfo] = None,
83
+ params: Optional[Params | Dict[str, Any]] = None,
84
+ coolant: Optional[Coolant | Dict[str, Any]] = None,
85
+ paginate: Optional[Paginate | Dict[str, Any]] = None,
86
+ retry: Optional[Retry | Dict[str, Any]] = None,
87
+ cache: Optional[Cache | Dict[str, str] | bool] = None,
88
+ ) -> None:
89
+ self.name: str = name
90
+ self.key: str = key
91
+ self.source: Optional[TableInfo] = source
92
+ self.target: Optional[TableInfo] = target
93
+ self.params: Params = self._resolve_params(params)
94
+ self.coolant: Coolant = self._resolve_coolant(coolant)
95
+ self.paginate: Paginate = self._resolve_paginate(paginate)
96
+ self.retry: Retry = self._resolve_retry(retry)
97
+ self.cache: Optional[Cache] = self._resolve_cache(cache)
98
+ self.metric: Metric = Metric()
99
+ self.markpoint("init[OK]")
100
+
101
+ def _resolve_params(
102
+ self,
103
+ params: Optional[Params | Dict[str, Any]],
104
+ ) -> Params:
105
+ if params is None:
106
+ return Params()
107
+ if isinstance(params, dict):
108
+ return Params(**params)
109
+ return params
110
+
111
+ def _resolve_coolant(
112
+ self,
113
+ coolant: Optional[Coolant | Dict[str, Any]],
114
+ ) -> Coolant:
115
+ if coolant is None:
116
+ return Coolant()
117
+ if isinstance(coolant, dict):
118
+ return Coolant.from_dict(coolant)
119
+ return coolant
120
+
121
+ def _resolve_paginate(
122
+ self,
123
+ paginate: Optional[Paginate | Dict[str, Any]],
124
+ ) -> Paginate:
125
+ if paginate is None:
126
+ return Paginate()
127
+ if isinstance(paginate, dict):
128
+ return Paginate.from_dict(paginate)
129
+ return paginate
130
+
131
+ def _resolve_retry(
132
+ self,
133
+ retry: Optional[Retry | Dict[str, Any]],
134
+ ) -> Retry:
135
+ if retry is None:
136
+ return Retry()
137
+ if isinstance(retry, dict):
138
+ return Retry.from_dict(retry)
139
+ return retry
140
+
141
+ def _resolve_cache(
142
+ self,
143
+ cache: Optional[Cache | Dict[str, str] | bool],
144
+ ) -> Optional[Cache]:
145
+ if isinstance(cache, bool):
146
+ if cache:
147
+ return Cache(identifier=self.name)
148
+ else:
149
+ return None
150
+ if isinstance(cache, dict):
151
+ return Cache.from_dict(cache)
152
+ if isinstance(cache, Cache):
153
+ return cache
154
+ return None
155
+
156
+ def run(self) -> Any:
157
+ wrapped = self.retry(self._run)
158
+ with self.metric:
159
+ return wrapped()
160
+
161
+ def _run(self) -> object:
162
+ msg = "Subclasses must implement this method."
163
+ raise NotImplementedError(msg)
164
+
165
+ def markpoint(
166
+ self,
167
+ name: str,
168
+ ) -> None:
169
+ self.metric.mark(name)
170
+
171
+ def cool(self) -> None:
172
+ self.coolant.cool()
173
+
174
+ def get_params(self) -> Dict[str, Any]:
175
+ return self.params.to_dict()
176
+
177
+ def get_cache(
178
+ self,
179
+ unit: str,
180
+ default: Any = None,
181
+ ) -> Optional[Any]:
182
+ if self.cache:
183
+ result = self.cache.get(unit)
184
+ if result is not None:
185
+ return result
186
+ return default
187
+
188
+ def set_cache(
189
+ self,
190
+ unit: str,
191
+ data: Any,
192
+ ) -> None:
193
+ if self.cache:
194
+ self.cache.set(unit, data)
195
+
196
+ def reset(self) -> None:
197
+ self.metric.reset()
198
+ if self.cache:
199
+ self.cache.clear()
200
+
201
+ def definition(self) -> Dict[str, Any]:
202
+ result = {}
203
+ if self.source:
204
+ result["source"] = self.source.describe()
205
+ if self.target:
206
+ result["target"] = self.target.describe()
207
+ return result
208
+
209
+ def specification(self) -> Dict[str, Any]:
210
+ result = {
211
+ "name": self.name,
212
+ "key": self.key,
213
+ "params": self.params.describe(),
214
+ "coolant": self.coolant.describe(),
215
+ "paginate": self.paginate.describe(),
216
+ "retry": self.retry.describe(),
217
+ "metric": self.metric.describe(),
218
+ }
219
+ if self.cache:
220
+ result["cache"] = self.cache.describe()
221
+ return result
222
+
223
+ def describe(self) -> Dict[str, Any]:
224
+ result = self.specification()
225
+ if self.source:
226
+ result["source"] = self.source.describe()
227
+ if self.target:
228
+ result["target"] = self.target.describe()
229
+ return result
230
+
231
+ def to_dict(self) -> Dict[str, Any]:
232
+ result = {
233
+ "name": self.name,
234
+ "key": self.key,
235
+ "params": self.params.to_dict(),
236
+ "coolant": self.coolant.to_dict(),
237
+ "paginate": self.paginate.to_dict(),
238
+ "retry": self.retry.to_dict(),
239
+ "metric": self.metric.to_dict(),
240
+ }
241
+ if self.source:
242
+ result["source"] = self.source.to_dict()
243
+ if self.target:
244
+ result["target"] = self.target.to_dict()
245
+ if self.cache:
246
+ result["cache"] = self.cache.to_dict()
247
+ return result
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Dict, Protocol, runtime_checkable
4
+
5
+
6
+ @runtime_checkable
7
+ class JobLike(Protocol):
8
+ """
9
+ 描述:
10
+ - 作业协议接口,定义作业类必须实现的核心方法。
11
+ - 使用 Protocol 实现结构化类型检查(structural typing)。
12
+ - 任何实现这些方法的类都会被视为符合 JobLike 协议。
13
+
14
+ 方法:
15
+ - run(): 执行作业并返回结果。
16
+ - _run(): 内部执行逻辑,由子类实现。
17
+ - describe(): 返回作业描述信息字典。
18
+ - to_dict(): 返回作业完整信息字典。
19
+
20
+ 例子:
21
+ ```python
22
+ from xfintech.data.job.joblike import JobLike
23
+
24
+ # 任何实现这些方法的类都符合 JobLike 协议
25
+ class MyJob:
26
+ def run(self) -> Any:
27
+ return self._run()
28
+
29
+ def _run(self) -> Any:
30
+ return {"result": "success"}
31
+
32
+ def describe(self) -> Dict[str, Any]:
33
+ return {"name": "MyJob"}
34
+
35
+ def to_dict(self) -> Dict[str, Any]:
36
+ return {"name": "MyJob", "status": "active"}
37
+
38
+ # 类型检查会通过
39
+ job: JobLike = MyJob()
40
+ result = job.run()
41
+ ```
42
+ """
43
+
44
+ def run(self) -> Any: ...
45
+ def _run(self) -> Any: ...
46
+ def describe(self) -> Dict[str, Any]: ...
47
+ def to_dict(self) -> Dict[str, Any]: ...
@@ -0,0 +1 @@
1
+ # Tests for xfintech.data.job module