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,705 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test suite for Session class
|
|
3
|
+
Tests cover initialization, connection modes, state management, and session lifecycle
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from unittest.mock import Mock, patch
|
|
8
|
+
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from xfintech.data.source.tushare.session.relay import RelayConnection
|
|
13
|
+
from xfintech.data.source.tushare.session.session import Session
|
|
14
|
+
|
|
15
|
+
# ============================================================================
|
|
16
|
+
# Session Initialization Tests - Direct Mode
|
|
17
|
+
# ============================================================================
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
21
|
+
def test_session_init_direct_mode_basic(mock_ts):
|
|
22
|
+
"""Test Session initialization in direct mode"""
|
|
23
|
+
mock_ts.pro_api.return_value = Mock()
|
|
24
|
+
|
|
25
|
+
session = Session(credential="test-token", mode="direct")
|
|
26
|
+
|
|
27
|
+
assert session.mode == "direct"
|
|
28
|
+
assert session._credential == "test-token"
|
|
29
|
+
assert session.relay_url is None
|
|
30
|
+
assert session.relay_secret is None
|
|
31
|
+
assert len(session.id) == 8
|
|
32
|
+
assert session.connected is True
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
36
|
+
def test_session_init_direct_mode_default(mock_ts):
|
|
37
|
+
"""Test Session defaults to direct mode"""
|
|
38
|
+
mock_ts.pro_api.return_value = Mock()
|
|
39
|
+
|
|
40
|
+
session = Session(credential="test-token")
|
|
41
|
+
|
|
42
|
+
assert session.mode == "direct"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
46
|
+
def test_session_init_direct_mode_uppercase(mock_ts):
|
|
47
|
+
"""Test Session handles uppercase mode"""
|
|
48
|
+
mock_ts.pro_api.return_value = Mock()
|
|
49
|
+
|
|
50
|
+
session = Session(credential="test-token", mode="DIRECT")
|
|
51
|
+
|
|
52
|
+
assert session.mode == "direct"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
56
|
+
def test_session_init_direct_sets_token(mock_ts):
|
|
57
|
+
"""Test Session sets tushare token in direct mode"""
|
|
58
|
+
mock_ts.pro_api.return_value = Mock()
|
|
59
|
+
|
|
60
|
+
Session(credential="test-token", mode="direct")
|
|
61
|
+
|
|
62
|
+
mock_ts.set_token.assert_called_once_with("test-token")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
66
|
+
def test_session_init_direct_creates_connection(mock_ts):
|
|
67
|
+
"""Test Session creates pro_api connection"""
|
|
68
|
+
mock_api = Mock()
|
|
69
|
+
mock_ts.pro_api.return_value = mock_api
|
|
70
|
+
|
|
71
|
+
session = Session(credential="test-token", mode="direct")
|
|
72
|
+
|
|
73
|
+
assert session.connection is mock_api
|
|
74
|
+
mock_ts.pro_api.assert_called_once()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# ============================================================================
|
|
78
|
+
# Session Initialization Tests - Relay Mode
|
|
79
|
+
# ============================================================================
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
|
|
83
|
+
def test_session_init_relay_mode_basic(mock_relay_client_class):
|
|
84
|
+
"""Test Session initialization in relay mode"""
|
|
85
|
+
mock_client = Mock()
|
|
86
|
+
mock_client.check_health.return_value = True
|
|
87
|
+
mock_relay_client_class.return_value = mock_client
|
|
88
|
+
|
|
89
|
+
session = Session(
|
|
90
|
+
credential="test-token",
|
|
91
|
+
mode="relay",
|
|
92
|
+
relay_url="https://relay.example.com",
|
|
93
|
+
relay_secret="relay-secret",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
assert session.mode == "relay"
|
|
97
|
+
assert session.relay_url == "https://relay.example.com"
|
|
98
|
+
assert session.relay_secret == "relay-secret"
|
|
99
|
+
assert session.connected is True
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
|
|
103
|
+
def test_session_init_relay_mode_creates_client(mock_relay_client_class):
|
|
104
|
+
"""Test Session creates RelayClient in relay mode"""
|
|
105
|
+
mock_client = Mock()
|
|
106
|
+
mock_client.check_health.return_value = True
|
|
107
|
+
mock_relay_client_class.return_value = mock_client
|
|
108
|
+
|
|
109
|
+
Session(
|
|
110
|
+
credential="test-token",
|
|
111
|
+
mode="relay",
|
|
112
|
+
relay_url="https://relay.example.com",
|
|
113
|
+
relay_secret="relay-secret",
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
mock_relay_client_class.assert_called_once_with(
|
|
117
|
+
url="https://relay.example.com",
|
|
118
|
+
secret="relay-secret",
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
|
|
123
|
+
def test_session_init_relay_mode_checks_health(mock_relay_client_class):
|
|
124
|
+
"""Test Session checks health in relay mode"""
|
|
125
|
+
mock_client = Mock()
|
|
126
|
+
mock_relay_client_class.return_value = mock_client
|
|
127
|
+
|
|
128
|
+
Session(
|
|
129
|
+
credential="test-token",
|
|
130
|
+
mode="relay",
|
|
131
|
+
relay_url="https://relay.example.com",
|
|
132
|
+
relay_secret="relay-secret",
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
mock_client.check_health.assert_called_once()
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
|
|
139
|
+
def test_session_init_relay_mode_connection_type(mock_relay_client_class):
|
|
140
|
+
"""Test Session connection is RelayConnection in relay mode"""
|
|
141
|
+
mock_client = Mock()
|
|
142
|
+
mock_client.check_health.return_value = True
|
|
143
|
+
mock_relay_client_class.return_value = mock_client
|
|
144
|
+
|
|
145
|
+
session = Session(
|
|
146
|
+
credential="test-token",
|
|
147
|
+
mode="relay",
|
|
148
|
+
relay_url="https://relay.example.com",
|
|
149
|
+
relay_secret="relay-secret",
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
assert isinstance(session.connection, RelayConnection)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def test_session_init_relay_mode_missing_url():
|
|
156
|
+
"""Test Session raises error when relay_url is missing in relay mode"""
|
|
157
|
+
with pytest.raises(ValueError, match="URL must be provided in relay mode"):
|
|
158
|
+
Session(
|
|
159
|
+
credential="test-token",
|
|
160
|
+
mode="relay",
|
|
161
|
+
relay_secret="relay-secret",
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def test_session_init_relay_mode_missing_secret():
|
|
166
|
+
"""Test Session raises error when relay_secret is missing in relay mode"""
|
|
167
|
+
with pytest.raises(ValueError, match="Secret must be provided in relay mode"):
|
|
168
|
+
Session(
|
|
169
|
+
credential="test-token",
|
|
170
|
+
mode="relay",
|
|
171
|
+
relay_url="https://relay.example.com",
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# ============================================================================
|
|
176
|
+
# Session Resolve Methods Tests
|
|
177
|
+
# ============================================================================
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def test_session_resolve_mode_invalid():
|
|
181
|
+
"""Test _resolve_mode raises error with invalid mode"""
|
|
182
|
+
with pytest.raises(ValueError, match="Unsupported mode"):
|
|
183
|
+
Session(credential="test-token", mode="invalid")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
187
|
+
def test_session_resolve_mode_empty_returns_direct(mock_ts):
|
|
188
|
+
"""Test _resolve_mode returns 'direct' for empty string"""
|
|
189
|
+
mock_ts.pro_api.return_value = Mock()
|
|
190
|
+
|
|
191
|
+
session = Session(credential="test-token", mode="")
|
|
192
|
+
|
|
193
|
+
assert session.mode == "direct"
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
# ============================================================================
|
|
197
|
+
# Session ID Tests
|
|
198
|
+
# ============================================================================
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
202
|
+
def test_session_id_length(mock_ts):
|
|
203
|
+
"""Test Session ID is 8 characters"""
|
|
204
|
+
mock_ts.pro_api.return_value = Mock()
|
|
205
|
+
|
|
206
|
+
session = Session(credential="test-token")
|
|
207
|
+
|
|
208
|
+
assert len(session.id) == 8
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
212
|
+
def test_session_id_unique(mock_ts):
|
|
213
|
+
"""Test different Sessions have different IDs"""
|
|
214
|
+
mock_ts.pro_api.return_value = Mock()
|
|
215
|
+
|
|
216
|
+
session1 = Session(credential="test-token")
|
|
217
|
+
session2 = Session(credential="test-token")
|
|
218
|
+
|
|
219
|
+
assert session1.id != session2.id
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# ============================================================================
|
|
223
|
+
# Session Properties Tests
|
|
224
|
+
# ============================================================================
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
228
|
+
def test_session_connected_property_true(mock_ts):
|
|
229
|
+
"""Test connected property returns True when connection exists"""
|
|
230
|
+
mock_ts.pro_api.return_value = Mock()
|
|
231
|
+
|
|
232
|
+
session = Session(credential="test-token")
|
|
233
|
+
|
|
234
|
+
assert session.connected is True
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
238
|
+
def test_session_connected_property_false(mock_ts):
|
|
239
|
+
"""Test connected property returns False when no connection"""
|
|
240
|
+
mock_ts.pro_api.return_value = Mock()
|
|
241
|
+
|
|
242
|
+
session = Session(credential="test-token")
|
|
243
|
+
session.connection = None
|
|
244
|
+
|
|
245
|
+
assert session.connected is False
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
249
|
+
@patch("xfintech.data.source.tushare.session.session.pd.Timestamp")
|
|
250
|
+
def test_session_duration_property_no_start(mock_timestamp, mock_ts):
|
|
251
|
+
"""Test duration returns 0.0 when not started"""
|
|
252
|
+
mock_ts.pro_api.return_value = Mock()
|
|
253
|
+
|
|
254
|
+
session = Session(credential="test-token")
|
|
255
|
+
session.start_at = None
|
|
256
|
+
|
|
257
|
+
assert session.duration == 0.0
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
261
|
+
def test_session_duration_property_ongoing(mock_ts):
|
|
262
|
+
"""Test duration calculates correctly for ongoing session"""
|
|
263
|
+
mock_ts.pro_api.return_value = Mock()
|
|
264
|
+
|
|
265
|
+
# Create session
|
|
266
|
+
session = Session(credential="test-token")
|
|
267
|
+
|
|
268
|
+
# Set times directly
|
|
269
|
+
session.start_at = pd.Timestamp("2024-01-15 10:00:00")
|
|
270
|
+
session.finish_at = None
|
|
271
|
+
|
|
272
|
+
# Mock datetime.now to return a specific time
|
|
273
|
+
with patch(
|
|
274
|
+
"xfintech.data.source.tushare.session.session.datetime",
|
|
275
|
+
) as mock_datetime:
|
|
276
|
+
mock_now = datetime(2024, 1, 15, 10, 0, 10)
|
|
277
|
+
mock_datetime.now.return_value = mock_now
|
|
278
|
+
|
|
279
|
+
duration = session.duration
|
|
280
|
+
|
|
281
|
+
assert duration == 10.0
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
285
|
+
def test_session_duration_property_finished(mock_ts):
|
|
286
|
+
"""Test duration calculates correctly for finished session"""
|
|
287
|
+
mock_ts.pro_api.return_value = Mock()
|
|
288
|
+
|
|
289
|
+
session = Session(credential="test-token")
|
|
290
|
+
session.start_at = pd.Timestamp("2024-01-15 10:00:00")
|
|
291
|
+
session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
|
|
292
|
+
|
|
293
|
+
assert session.duration == 30.0
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
# ============================================================================
|
|
297
|
+
# Session String Representation Tests
|
|
298
|
+
# ============================================================================
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
302
|
+
def test_session_str(mock_ts):
|
|
303
|
+
"""Test __str__ returns session ID"""
|
|
304
|
+
mock_ts.pro_api.return_value = Mock()
|
|
305
|
+
|
|
306
|
+
session = Session(credential="test-token")
|
|
307
|
+
|
|
308
|
+
assert str(session) == session.id
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
312
|
+
def test_session_repr(mock_ts):
|
|
313
|
+
"""Test __repr__ includes class name, connected status, and mode"""
|
|
314
|
+
mock_ts.pro_api.return_value = Mock()
|
|
315
|
+
|
|
316
|
+
session = Session(credential="test-token", mode="direct")
|
|
317
|
+
|
|
318
|
+
result = repr(session)
|
|
319
|
+
assert "Session" in result
|
|
320
|
+
assert "connected=True" in result
|
|
321
|
+
assert "mode=direct" in result
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
@patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
|
|
325
|
+
def test_session_repr_relay_mode(mock_relay_client_class):
|
|
326
|
+
"""Test __repr__ shows relay mode"""
|
|
327
|
+
mock_client = Mock()
|
|
328
|
+
mock_client.check_health.return_value = True
|
|
329
|
+
mock_relay_client_class.return_value = mock_client
|
|
330
|
+
|
|
331
|
+
session = Session(
|
|
332
|
+
credential="test-token",
|
|
333
|
+
mode="relay",
|
|
334
|
+
relay_url="https://relay.example.com",
|
|
335
|
+
relay_secret="relay-secret",
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
result = repr(session)
|
|
339
|
+
assert "mode=relay" in result
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
# ============================================================================
|
|
343
|
+
# Session Start/End Methods Tests
|
|
344
|
+
# ============================================================================
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
348
|
+
@patch("xfintech.data.source.tushare.session.session.pd.Timestamp")
|
|
349
|
+
def test_session_start_method(mock_timestamp, mock_ts):
|
|
350
|
+
"""Test start method sets start_at"""
|
|
351
|
+
mock_ts.pro_api.return_value = Mock()
|
|
352
|
+
mock_now = pd.Timestamp("2024-01-15 10:00:00")
|
|
353
|
+
mock_timestamp.now.return_value = mock_now
|
|
354
|
+
|
|
355
|
+
session = Session(credential="test-token")
|
|
356
|
+
session.start_at = None
|
|
357
|
+
session.start()
|
|
358
|
+
|
|
359
|
+
assert session.start_at == mock_now
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
363
|
+
@patch("xfintech.data.source.tushare.session.session.pd.Timestamp")
|
|
364
|
+
def test_session_end_method(mock_timestamp, mock_ts):
|
|
365
|
+
"""Test end method sets finish_at"""
|
|
366
|
+
mock_ts.pro_api.return_value = Mock()
|
|
367
|
+
mock_now = pd.Timestamp("2024-01-15 10:00:30")
|
|
368
|
+
mock_timestamp.now.return_value = mock_now
|
|
369
|
+
|
|
370
|
+
session = Session(credential="test-token")
|
|
371
|
+
session.end()
|
|
372
|
+
|
|
373
|
+
assert session.finish_at == mock_now
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
377
|
+
def test_session_get_start_iso_none(mock_ts):
|
|
378
|
+
"""Test get_start_iso returns None when start_at is None"""
|
|
379
|
+
mock_ts.pro_api.return_value = Mock()
|
|
380
|
+
|
|
381
|
+
session = Session(credential="test-token")
|
|
382
|
+
session.start_at = None
|
|
383
|
+
|
|
384
|
+
assert session.get_start_iso() is None
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
388
|
+
def test_session_get_start_iso_with_value(mock_ts):
|
|
389
|
+
"""Test get_start_iso returns ISO format"""
|
|
390
|
+
mock_ts.pro_api.return_value = Mock()
|
|
391
|
+
|
|
392
|
+
session = Session(credential="test-token")
|
|
393
|
+
session.start_at = pd.Timestamp("2024-01-15 10:00:00")
|
|
394
|
+
|
|
395
|
+
result = session.get_start_iso()
|
|
396
|
+
assert "2024-01-15" in result
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
400
|
+
def test_session_get_finish_iso_none(mock_ts):
|
|
401
|
+
"""Test get_finish_iso returns None when finish_at is None"""
|
|
402
|
+
mock_ts.pro_api.return_value = Mock()
|
|
403
|
+
|
|
404
|
+
session = Session(credential="test-token")
|
|
405
|
+
session.finish_at = None
|
|
406
|
+
|
|
407
|
+
assert session.get_finish_iso() is None
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
411
|
+
def test_session_get_finish_iso_with_value(mock_ts):
|
|
412
|
+
"""Test get_finish_iso returns ISO format"""
|
|
413
|
+
mock_ts.pro_api.return_value = Mock()
|
|
414
|
+
|
|
415
|
+
session = Session(credential="test-token")
|
|
416
|
+
session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
|
|
417
|
+
|
|
418
|
+
result = session.get_finish_iso()
|
|
419
|
+
assert "2024-01-15" in result
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
# ============================================================================
|
|
423
|
+
# Session Connect/Disconnect Tests
|
|
424
|
+
# ============================================================================
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
428
|
+
def test_session_connect_returns_connection(mock_ts):
|
|
429
|
+
"""Test connect returns connection object"""
|
|
430
|
+
mock_api = Mock()
|
|
431
|
+
mock_ts.pro_api.return_value = mock_api
|
|
432
|
+
|
|
433
|
+
session = Session(credential="test-token")
|
|
434
|
+
session.connection = None
|
|
435
|
+
|
|
436
|
+
result = session.connect()
|
|
437
|
+
|
|
438
|
+
assert result is not None
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
442
|
+
def test_session_connect_already_connected(mock_ts):
|
|
443
|
+
"""Test connect returns existing connection if already connected"""
|
|
444
|
+
mock_api = Mock()
|
|
445
|
+
mock_ts.pro_api.return_value = mock_api
|
|
446
|
+
|
|
447
|
+
session = Session(credential="test-token")
|
|
448
|
+
first_connection = session.connection
|
|
449
|
+
|
|
450
|
+
# Reset call count
|
|
451
|
+
mock_ts.pro_api.reset_mock()
|
|
452
|
+
|
|
453
|
+
# Try to connect again
|
|
454
|
+
result = session.connect()
|
|
455
|
+
|
|
456
|
+
assert result is first_connection
|
|
457
|
+
# Should not create new connection
|
|
458
|
+
mock_ts.pro_api.assert_not_called()
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
462
|
+
@patch("xfintech.data.source.tushare.session.session.pd.Timestamp")
|
|
463
|
+
def test_session_disconnect_clears_connection(mock_timestamp, mock_ts):
|
|
464
|
+
"""Test disconnect clears connection"""
|
|
465
|
+
mock_ts.pro_api.return_value = Mock()
|
|
466
|
+
|
|
467
|
+
session = Session(credential="test-token")
|
|
468
|
+
assert session.connected is True
|
|
469
|
+
|
|
470
|
+
session.disconnect()
|
|
471
|
+
|
|
472
|
+
assert session.connection is None
|
|
473
|
+
assert session.connected is False
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
477
|
+
@patch("xfintech.data.source.tushare.session.session.pd.Timestamp")
|
|
478
|
+
def test_session_disconnect_sets_finish_time(mock_timestamp, mock_ts):
|
|
479
|
+
"""Test disconnect sets finish_at"""
|
|
480
|
+
mock_ts.pro_api.return_value = Mock()
|
|
481
|
+
mock_now = pd.Timestamp("2024-01-15 10:00:30")
|
|
482
|
+
mock_timestamp.now.return_value = mock_now
|
|
483
|
+
|
|
484
|
+
session = Session(credential="test-token")
|
|
485
|
+
session.disconnect()
|
|
486
|
+
|
|
487
|
+
assert session.finish_at == mock_now
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
# ============================================================================
|
|
491
|
+
# Session Describe Method Tests
|
|
492
|
+
# ============================================================================
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
496
|
+
def test_session_describe_basic(mock_ts):
|
|
497
|
+
"""Test describe returns basic session info"""
|
|
498
|
+
mock_ts.pro_api.return_value = Mock()
|
|
499
|
+
|
|
500
|
+
session = Session(credential="test-token", mode="direct")
|
|
501
|
+
result = session.describe()
|
|
502
|
+
|
|
503
|
+
assert "id" in result
|
|
504
|
+
assert result["id"] == session.id
|
|
505
|
+
assert "mode" in result
|
|
506
|
+
assert result["mode"] == "direct"
|
|
507
|
+
assert "connected" in result
|
|
508
|
+
assert result["connected"] is True
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
512
|
+
def test_session_describe_masks_credential(mock_ts):
|
|
513
|
+
"""Test describe masks credential"""
|
|
514
|
+
mock_ts.pro_api.return_value = Mock()
|
|
515
|
+
|
|
516
|
+
session = Session(credential="test-token")
|
|
517
|
+
result = session.describe()
|
|
518
|
+
|
|
519
|
+
assert result["credential"] == "******"
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
523
|
+
def test_session_describe_no_credential(mock_ts):
|
|
524
|
+
"""Test describe handles None credential"""
|
|
525
|
+
mock_ts.pro_api.return_value = Mock()
|
|
526
|
+
|
|
527
|
+
session = Session(credential=None)
|
|
528
|
+
result = session.describe()
|
|
529
|
+
|
|
530
|
+
assert "credential" not in result
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
@patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
|
|
534
|
+
def test_session_describe_relay_mode(mock_relay_client_class):
|
|
535
|
+
"""Test describe includes relay info in relay mode"""
|
|
536
|
+
mock_client = Mock()
|
|
537
|
+
mock_client.check_health.return_value = True
|
|
538
|
+
mock_relay_client_class.return_value = mock_client
|
|
539
|
+
|
|
540
|
+
session = Session(
|
|
541
|
+
credential="test-token",
|
|
542
|
+
mode="relay",
|
|
543
|
+
relay_url="https://relay.example.com",
|
|
544
|
+
relay_secret="relay-secret",
|
|
545
|
+
)
|
|
546
|
+
result = session.describe()
|
|
547
|
+
|
|
548
|
+
assert "relay" in result
|
|
549
|
+
assert result["relay"]["url"] == "https://relay.example.com"
|
|
550
|
+
assert result["relay"]["secret"] == "******"
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
554
|
+
def test_session_describe_with_timestamps(mock_ts):
|
|
555
|
+
"""Test describe includes timestamps when available"""
|
|
556
|
+
mock_ts.pro_api.return_value = Mock()
|
|
557
|
+
|
|
558
|
+
session = Session(credential="test-token")
|
|
559
|
+
session.start_at = pd.Timestamp("2024-01-15 10:00:00")
|
|
560
|
+
session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
|
|
561
|
+
|
|
562
|
+
result = session.describe()
|
|
563
|
+
|
|
564
|
+
assert "start_at" in result
|
|
565
|
+
assert "finish_at" in result
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
569
|
+
def test_session_describe_without_finish(mock_ts):
|
|
570
|
+
"""Test describe handles ongoing session"""
|
|
571
|
+
mock_ts.pro_api.return_value = Mock()
|
|
572
|
+
|
|
573
|
+
session = Session(credential="test-token")
|
|
574
|
+
session.finish_at = None
|
|
575
|
+
|
|
576
|
+
result = session.describe()
|
|
577
|
+
|
|
578
|
+
assert "start_at" in result
|
|
579
|
+
assert "finish_at" not in result
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
# ============================================================================
|
|
583
|
+
# Session To Dict Method Tests
|
|
584
|
+
# ============================================================================
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
588
|
+
def test_session_to_dict_structure(mock_ts):
|
|
589
|
+
"""Test to_dict returns expected structure"""
|
|
590
|
+
mock_ts.pro_api.return_value = Mock()
|
|
591
|
+
|
|
592
|
+
session = Session(credential="test-token", mode="direct")
|
|
593
|
+
result = session.to_dict()
|
|
594
|
+
|
|
595
|
+
assert "id" in result
|
|
596
|
+
assert "connected" in result
|
|
597
|
+
assert "credential" in result
|
|
598
|
+
assert "mode" in result
|
|
599
|
+
assert "relay" in result
|
|
600
|
+
assert "start_at" in result
|
|
601
|
+
assert "finish_at" in result
|
|
602
|
+
assert "duration" in result
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
@patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
|
|
606
|
+
def test_session_to_dict_masks_credential(mock_ts):
|
|
607
|
+
"""Test to_dict masks credential"""
|
|
608
|
+
mock_ts.pro_api.return_value = Mock()
|
|
609
|
+
|
|
610
|
+
session = Session(credential="test-token")
|
|
611
|
+
result = session.to_dict()
|
|
612
|
+
|
|
613
|
+
assert result["credential"] == "******"
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
617
|
+
def test_session_to_dict_none_credential(mock_ts):
|
|
618
|
+
"""Test to_dict handles None credential"""
|
|
619
|
+
mock_ts.pro_api.return_value = Mock()
|
|
620
|
+
|
|
621
|
+
session = Session(credential=None)
|
|
622
|
+
result = session.to_dict()
|
|
623
|
+
|
|
624
|
+
assert result["credential"] is None
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
628
|
+
def test_session_to_dict_includes_duration(mock_ts):
|
|
629
|
+
"""Test to_dict includes duration"""
|
|
630
|
+
mock_ts.pro_api.return_value = Mock()
|
|
631
|
+
|
|
632
|
+
session = Session(credential="test-token")
|
|
633
|
+
session.start_at = pd.Timestamp("2024-01-15 10:00:00")
|
|
634
|
+
session.finish_at = pd.Timestamp("2024-01-15 10:00:30")
|
|
635
|
+
|
|
636
|
+
result = session.to_dict()
|
|
637
|
+
|
|
638
|
+
assert result["duration"] == 30.0
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
# ============================================================================
|
|
642
|
+
# Integration Tests
|
|
643
|
+
# ============================================================================
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
647
|
+
def test_session_full_lifecycle_direct(mock_ts):
|
|
648
|
+
"""Test complete session lifecycle in direct mode"""
|
|
649
|
+
mock_api = Mock()
|
|
650
|
+
mock_ts.pro_api.return_value = mock_api
|
|
651
|
+
|
|
652
|
+
# Create session
|
|
653
|
+
session = Session(credential="test-token", mode="direct")
|
|
654
|
+
assert session.connected is True
|
|
655
|
+
|
|
656
|
+
# Use connection
|
|
657
|
+
assert session.connection is mock_api
|
|
658
|
+
|
|
659
|
+
# Disconnect
|
|
660
|
+
session.disconnect()
|
|
661
|
+
assert session.connected is False
|
|
662
|
+
assert session.finish_at is not None
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
@patch("xfintech.data.source.tushare.session.session.TushareRelayClient")
|
|
666
|
+
def test_session_full_lifecycle_relay(mock_relay_client_class):
|
|
667
|
+
"""Test complete session lifecycle in relay mode"""
|
|
668
|
+
mock_client = Mock()
|
|
669
|
+
mock_client.check_health.return_value = True
|
|
670
|
+
mock_relay_client_class.return_value = mock_client
|
|
671
|
+
|
|
672
|
+
# Create session
|
|
673
|
+
session = Session(
|
|
674
|
+
credential="test-token",
|
|
675
|
+
mode="relay",
|
|
676
|
+
relay_url="https://relay.example.com",
|
|
677
|
+
relay_secret="relay-secret",
|
|
678
|
+
)
|
|
679
|
+
assert session.connected is True
|
|
680
|
+
assert isinstance(session.connection, RelayConnection)
|
|
681
|
+
|
|
682
|
+
# Get description
|
|
683
|
+
desc = session.describe()
|
|
684
|
+
assert desc["mode"] == "relay"
|
|
685
|
+
assert desc["relay"]["secret"] == "******"
|
|
686
|
+
|
|
687
|
+
# Disconnect
|
|
688
|
+
session.disconnect()
|
|
689
|
+
assert session.connected is False
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
@patch("xfintech.data.source.tushare.session.session.ts")
|
|
693
|
+
def test_session_reconnect(mock_ts):
|
|
694
|
+
"""Test reconnecting after disconnect"""
|
|
695
|
+
mock_api = Mock()
|
|
696
|
+
mock_ts.pro_api.return_value = mock_api
|
|
697
|
+
|
|
698
|
+
session = Session(credential="test-token")
|
|
699
|
+
session.disconnect()
|
|
700
|
+
|
|
701
|
+
# Reconnect
|
|
702
|
+
session.connect()
|
|
703
|
+
|
|
704
|
+
assert session.connected is True
|
|
705
|
+
assert session.connection is not None
|