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