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,586 @@
|
|
|
1
|
+
"""
|
|
2
|
+
描述:
|
|
3
|
+
- ConnectRefLike 协议和 ConnectRef 类的单元测试。
|
|
4
|
+
- 测试协议的结构、ConnectRef 的功能和边界情况。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Dict, Optional
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
from xfintech.connect.common.connectref import ConnectRef, ConnectRefLike
|
|
14
|
+
from xfintech.connect.common.error import ConnectRefKeyError
|
|
15
|
+
|
|
16
|
+
# =============================================================================
|
|
17
|
+
# ConnectRefLike Protocol Tests
|
|
18
|
+
# =============================================================================
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_connectreflike_is_protocol():
|
|
22
|
+
"""测试 ConnectRefLike 是一个协议类"""
|
|
23
|
+
from typing import Protocol
|
|
24
|
+
|
|
25
|
+
assert issubclass(ConnectRefLike.__class__, type(Protocol))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_connectreflike_is_runtime_checkable():
|
|
29
|
+
"""测试 ConnectRefLike 是运行时可检查的"""
|
|
30
|
+
# Check for protocol marker attributes that exist in Python 3.8+
|
|
31
|
+
assert hasattr(ConnectRefLike, "_is_protocol") or hasattr(ConnectRefLike, "__protocol_attrs__")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_connectreflike_has_required_attributes():
|
|
35
|
+
"""测试 ConnectRefLike 定义了必需的属性"""
|
|
36
|
+
|
|
37
|
+
annotations = ConnectRefLike.__annotations__
|
|
38
|
+
assert "location" in annotations
|
|
39
|
+
assert "kind" in annotations
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_connectreflike_has_describe_method():
|
|
43
|
+
"""测试 ConnectRefLike 定义了 describe 方法"""
|
|
44
|
+
assert hasattr(ConnectRefLike, "describe")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_connectreflike_has_to_dict_method():
|
|
48
|
+
"""测试 ConnectRefLike 定义了 to_dict 方法"""
|
|
49
|
+
assert hasattr(ConnectRefLike, "to_dict")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_valid_connectreflike_implementation():
|
|
53
|
+
"""测试有效的 ConnectRefLike 实现"""
|
|
54
|
+
|
|
55
|
+
class MyRef:
|
|
56
|
+
def __init__(self):
|
|
57
|
+
self.location = "test"
|
|
58
|
+
self.kind = "test"
|
|
59
|
+
|
|
60
|
+
def describe(self) -> Dict[str, Optional[str]]:
|
|
61
|
+
return {"location": self.location}
|
|
62
|
+
|
|
63
|
+
def to_dict(self) -> Dict[str, Optional[str]]:
|
|
64
|
+
return {"location": self.location, "kind": self.kind}
|
|
65
|
+
|
|
66
|
+
ref = MyRef()
|
|
67
|
+
assert isinstance(ref, ConnectRefLike)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_invalid_connectreflike_missing_location():
|
|
71
|
+
"""测试缺少 location 属性的实现"""
|
|
72
|
+
|
|
73
|
+
class InvalidRef:
|
|
74
|
+
def __init__(self):
|
|
75
|
+
self.kind = "test"
|
|
76
|
+
|
|
77
|
+
def describe(self) -> Dict[str, Optional[str]]:
|
|
78
|
+
return {}
|
|
79
|
+
|
|
80
|
+
def to_dict(self) -> Dict[str, Optional[str]]:
|
|
81
|
+
return {}
|
|
82
|
+
|
|
83
|
+
ref = InvalidRef()
|
|
84
|
+
assert not isinstance(ref, ConnectRefLike)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# =============================================================================
|
|
88
|
+
# ConnectRef Initialization Tests
|
|
89
|
+
# =============================================================================
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_connectref_init_with_location_only():
|
|
93
|
+
"""测试仅使用 location 初始化"""
|
|
94
|
+
ref = ConnectRef(location="test_location")
|
|
95
|
+
assert ref.location == "test_location"
|
|
96
|
+
assert ref.kind is None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def test_connectref_init_with_location_and_kind():
|
|
100
|
+
"""测试使用 location 和 kind 初始化"""
|
|
101
|
+
ref = ConnectRef(location="test_location", kind="s3")
|
|
102
|
+
assert ref.location == "test_location"
|
|
103
|
+
assert ref.kind == "s3"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_connectref_init_empty_location():
|
|
107
|
+
"""测试空字符串 location"""
|
|
108
|
+
ref = ConnectRef(location="")
|
|
109
|
+
assert ref.location == ""
|
|
110
|
+
assert ref.kind is None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_connectref_init_none_kind():
|
|
114
|
+
"""测试显式 None 的 kind"""
|
|
115
|
+
ref = ConnectRef(location="loc", kind=None)
|
|
116
|
+
assert ref.location == "loc"
|
|
117
|
+
assert ref.kind is None
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def test_connectref_is_connectreflike():
|
|
121
|
+
"""测试 ConnectRef 是 ConnectRefLike 的实例"""
|
|
122
|
+
ref = ConnectRef(location="test")
|
|
123
|
+
assert isinstance(ref, ConnectRefLike)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# =============================================================================
|
|
127
|
+
# ConnectRef.from_dict Tests
|
|
128
|
+
# =============================================================================
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def test_from_dict_with_location_only():
|
|
132
|
+
"""测试从仅包含 location 的字典创建"""
|
|
133
|
+
data = {"location": "test_loc"}
|
|
134
|
+
ref = ConnectRef.from_dict(data)
|
|
135
|
+
assert ref.location == "test_loc"
|
|
136
|
+
assert ref.kind is None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def test_from_dict_with_location_and_kind():
|
|
140
|
+
"""测试从包含 location 和 kind 的字典创建"""
|
|
141
|
+
data = {"location": "test_loc", "kind": "s3"}
|
|
142
|
+
ref = ConnectRef.from_dict(data)
|
|
143
|
+
assert ref.location == "test_loc"
|
|
144
|
+
assert ref.kind == "s3"
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def test_from_dict_missing_location_raises_error():
|
|
148
|
+
"""测试缺少 location 键抛出错误"""
|
|
149
|
+
data = {"kind": "s3"}
|
|
150
|
+
with pytest.raises(ConnectRefKeyError) as excinfo:
|
|
151
|
+
ConnectRef.from_dict(data)
|
|
152
|
+
assert "'location' is required in data" in str(excinfo.value)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def test_from_dict_empty_dict_raises_error():
|
|
156
|
+
"""测试空字典抛出错误"""
|
|
157
|
+
with pytest.raises(ConnectRefKeyError):
|
|
158
|
+
ConnectRef.from_dict({})
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def test_from_dict_with_extra_keys():
|
|
162
|
+
"""测试包含额外键的字典"""
|
|
163
|
+
data = {"location": "loc", "kind": "s3", "extra": "ignored"}
|
|
164
|
+
ref = ConnectRef.from_dict(data)
|
|
165
|
+
assert ref.location == "loc"
|
|
166
|
+
assert ref.kind == "s3"
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def test_from_dict_none_kind():
|
|
170
|
+
"""测试 kind 为 None 的字典"""
|
|
171
|
+
data = {"location": "loc", "kind": None}
|
|
172
|
+
ref = ConnectRef.from_dict(data)
|
|
173
|
+
assert ref.location == "loc"
|
|
174
|
+
assert ref.kind is None
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def test_from_dict_location_type_conversion():
|
|
178
|
+
"""测试 location 类型转换"""
|
|
179
|
+
data = {"location": 123}
|
|
180
|
+
ref = ConnectRef.from_dict(data)
|
|
181
|
+
assert ref.location == "123"
|
|
182
|
+
assert isinstance(ref.location, str)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def test_from_dict_with_mapping_type():
|
|
186
|
+
"""测试使用 Mapping 类型"""
|
|
187
|
+
from collections import OrderedDict
|
|
188
|
+
|
|
189
|
+
data = OrderedDict([("location", "test"), ("kind", "macos")])
|
|
190
|
+
ref = ConnectRef.from_dict(data)
|
|
191
|
+
assert ref.location == "test"
|
|
192
|
+
assert ref.kind == "macos"
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# =============================================================================
|
|
196
|
+
# ConnectRef String Representation Tests
|
|
197
|
+
# =============================================================================
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def test_str_returns_location():
|
|
201
|
+
"""测试 __str__ 返回 location"""
|
|
202
|
+
ref = ConnectRef(location="test_location")
|
|
203
|
+
assert str(ref) == "test_location"
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def test_str_with_kind():
|
|
207
|
+
"""测试带 kind 的 __str__"""
|
|
208
|
+
ref = ConnectRef(location="test_location", kind="s3")
|
|
209
|
+
assert str(ref) == "test_location"
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def test_repr_format():
|
|
213
|
+
"""测试 __repr__ 格式"""
|
|
214
|
+
ref = ConnectRef(location="test_location", kind="s3")
|
|
215
|
+
repr_str = repr(ref)
|
|
216
|
+
assert "ConnectRef" in repr_str
|
|
217
|
+
assert "location=test_location" in repr_str
|
|
218
|
+
assert "kind=s3" in repr_str
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def test_repr_without_kind():
|
|
222
|
+
"""测试没有 kind 的 __repr__"""
|
|
223
|
+
ref = ConnectRef(location="test_location")
|
|
224
|
+
repr_str = repr(ref)
|
|
225
|
+
assert "ConnectRef" in repr_str
|
|
226
|
+
assert "location=test_location" in repr_str
|
|
227
|
+
assert "kind=None" in repr_str
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def test_repr_can_be_evaluated():
|
|
231
|
+
"""测试 __repr__ 可以被评估(手动检查)"""
|
|
232
|
+
ref = ConnectRef(location="test", kind="s3")
|
|
233
|
+
repr_str = repr(ref)
|
|
234
|
+
# Manual check - repr shows the structure clearly
|
|
235
|
+
assert "test" in repr_str
|
|
236
|
+
assert "s3" in repr_str
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
# =============================================================================
|
|
240
|
+
# ConnectRef Equality Tests
|
|
241
|
+
# =============================================================================
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def test_equality_same_location_and_kind():
|
|
245
|
+
"""测试相同 location 和 kind 的相等性"""
|
|
246
|
+
ref1 = ConnectRef(location="test", kind="s3")
|
|
247
|
+
ref2 = ConnectRef(location="test", kind="s3")
|
|
248
|
+
assert ref1 == ref2
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def test_equality_same_location_no_kind():
|
|
252
|
+
"""测试相同 location 无 kind 的相等性"""
|
|
253
|
+
ref1 = ConnectRef(location="test")
|
|
254
|
+
ref2 = ConnectRef(location="test")
|
|
255
|
+
assert ref1 == ref2
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def test_inequality_different_location():
|
|
259
|
+
"""测试不同 location 的不相等性"""
|
|
260
|
+
ref1 = ConnectRef(location="test1", kind="s3")
|
|
261
|
+
ref2 = ConnectRef(location="test2", kind="s3")
|
|
262
|
+
assert ref1 != ref2
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def test_inequality_different_kind():
|
|
266
|
+
"""测试不同 kind 的不相等性"""
|
|
267
|
+
ref1 = ConnectRef(location="test", kind="s3")
|
|
268
|
+
ref2 = ConnectRef(location="test", kind="macos")
|
|
269
|
+
assert ref1 != ref2
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def test_inequality_one_has_kind():
|
|
273
|
+
"""测试一个有 kind 一个无 kind 的不相等性"""
|
|
274
|
+
ref1 = ConnectRef(location="test", kind="s3")
|
|
275
|
+
ref2 = ConnectRef(location="test")
|
|
276
|
+
assert ref1 != ref2
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def test_equality_with_non_connectref():
|
|
280
|
+
"""测试与非 ConnectRef 对象的比较"""
|
|
281
|
+
ref = ConnectRef(location="test")
|
|
282
|
+
assert ref != "test"
|
|
283
|
+
assert ref != 123
|
|
284
|
+
assert ref is not None
|
|
285
|
+
assert ref != {"location": "test"}
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def test_equality_reflexive():
|
|
289
|
+
"""测试相等性的自反性"""
|
|
290
|
+
ref = ConnectRef(location="test", kind="s3")
|
|
291
|
+
assert ref == ref
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def test_equality_symmetric():
|
|
295
|
+
"""测试相等性的对称性"""
|
|
296
|
+
ref1 = ConnectRef(location="test", kind="s3")
|
|
297
|
+
ref2 = ConnectRef(location="test", kind="s3")
|
|
298
|
+
assert ref1 == ref2
|
|
299
|
+
assert ref2 == ref1
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def test_equality_transitive():
|
|
303
|
+
"""测试相等性的传递性"""
|
|
304
|
+
ref1 = ConnectRef(location="test", kind="s3")
|
|
305
|
+
ref2 = ConnectRef(location="test", kind="s3")
|
|
306
|
+
ref3 = ConnectRef(location="test", kind="s3")
|
|
307
|
+
assert ref1 == ref2
|
|
308
|
+
assert ref2 == ref3
|
|
309
|
+
assert ref1 == ref3
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
# =============================================================================
|
|
313
|
+
# ConnectRef Hash Tests
|
|
314
|
+
# =============================================================================
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def test_hash_same_values():
|
|
318
|
+
"""测试相同值的哈希相同"""
|
|
319
|
+
ref1 = ConnectRef(location="test", kind="s3")
|
|
320
|
+
ref2 = ConnectRef(location="test", kind="s3")
|
|
321
|
+
assert hash(ref1) == hash(ref2)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def test_hash_different_values():
|
|
325
|
+
"""测试不同值的哈希可能不同"""
|
|
326
|
+
ref1 = ConnectRef(location="test1", kind="s3")
|
|
327
|
+
ref2 = ConnectRef(location="test2", kind="s3")
|
|
328
|
+
# Hashes might collide, but typically different
|
|
329
|
+
# Just test they are hashable
|
|
330
|
+
assert isinstance(hash(ref1), int)
|
|
331
|
+
assert isinstance(hash(ref2), int)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def test_can_use_in_set():
|
|
335
|
+
"""测试可以在集合中使用"""
|
|
336
|
+
ref1 = ConnectRef(location="test1", kind="s3")
|
|
337
|
+
ref2 = ConnectRef(location="test2", kind="s3")
|
|
338
|
+
ref3 = ConnectRef(location="test1", kind="s3")
|
|
339
|
+
|
|
340
|
+
ref_set = {ref1, ref2, ref3}
|
|
341
|
+
assert len(ref_set) == 2 # ref1 and ref3 are equal
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def test_can_use_as_dict_key():
|
|
345
|
+
"""测试可以作为字典键使用"""
|
|
346
|
+
ref1 = ConnectRef(location="test1", kind="s3")
|
|
347
|
+
ref2 = ConnectRef(location="test2", kind="s3")
|
|
348
|
+
|
|
349
|
+
data = {ref1: "value1", ref2: "value2"}
|
|
350
|
+
assert data[ref1] == "value1"
|
|
351
|
+
assert data[ref2] == "value2"
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def test_hash_consistent_with_equality():
|
|
355
|
+
"""测试哈希与相等性一致"""
|
|
356
|
+
ref1 = ConnectRef(location="test", kind="s3")
|
|
357
|
+
ref2 = ConnectRef(location="test", kind="s3")
|
|
358
|
+
|
|
359
|
+
if ref1 == ref2:
|
|
360
|
+
assert hash(ref1) == hash(ref2)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
# =============================================================================
|
|
364
|
+
# ConnectRef.describe Tests
|
|
365
|
+
# =============================================================================
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def test_describe_with_location_only():
|
|
369
|
+
"""测试仅 location 的描述"""
|
|
370
|
+
ref = ConnectRef(location="test_location")
|
|
371
|
+
result = ref.describe()
|
|
372
|
+
assert result == {"location": "test_location"}
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def test_describe_with_location_and_kind():
|
|
376
|
+
"""测试带 kind 的描述"""
|
|
377
|
+
ref = ConnectRef(location="test_location", kind="s3")
|
|
378
|
+
result = ref.describe()
|
|
379
|
+
assert result == {"location": "test_location", "kind": "s3"}
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def test_describe_kind_none_not_included():
|
|
383
|
+
"""测试 kind 为 None 时不包含在描述中"""
|
|
384
|
+
ref = ConnectRef(location="test", kind=None)
|
|
385
|
+
result = ref.describe()
|
|
386
|
+
assert "kind" not in result
|
|
387
|
+
assert result == {"location": "test"}
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def test_describe_returns_dict():
|
|
391
|
+
"""测试 describe 返回字典类型"""
|
|
392
|
+
ref = ConnectRef(location="test")
|
|
393
|
+
result = ref.describe()
|
|
394
|
+
assert isinstance(result, dict)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def test_describe_empty_kind_string():
|
|
398
|
+
"""测试空字符串 kind"""
|
|
399
|
+
ref = ConnectRef(location="test", kind="")
|
|
400
|
+
result = ref.describe()
|
|
401
|
+
# Empty string is falsy, so not included
|
|
402
|
+
assert "kind" not in result
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
# =============================================================================
|
|
406
|
+
# ConnectRef.to_dict Tests
|
|
407
|
+
# =============================================================================
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def test_to_dict_with_location_only():
|
|
411
|
+
"""测试仅 location 的字典转换"""
|
|
412
|
+
ref = ConnectRef(location="test_location")
|
|
413
|
+
result = ref.to_dict()
|
|
414
|
+
assert result == {"location": "test_location"}
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def test_to_dict_with_location_and_kind():
|
|
418
|
+
"""测试带 kind 的字典转换"""
|
|
419
|
+
ref = ConnectRef(location="test_location", kind="s3")
|
|
420
|
+
result = ref.to_dict()
|
|
421
|
+
assert result == {"location": "test_location", "kind": "s3"}
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def test_to_dict_kind_none_not_included():
|
|
425
|
+
"""测试 kind 为 None 时不包含"""
|
|
426
|
+
ref = ConnectRef(location="test")
|
|
427
|
+
result = ref.to_dict()
|
|
428
|
+
assert "kind" not in result
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def test_to_dict_returns_dict():
|
|
432
|
+
"""测试 to_dict 返回字典类型"""
|
|
433
|
+
ref = ConnectRef(location="test")
|
|
434
|
+
result = ref.to_dict()
|
|
435
|
+
assert isinstance(result, dict)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def test_to_dict_roundtrip():
|
|
439
|
+
"""测试 to_dict 和 from_dict 往返"""
|
|
440
|
+
original = ConnectRef(location="test_loc", kind="s3")
|
|
441
|
+
data = original.to_dict()
|
|
442
|
+
restored = ConnectRef.from_dict(data)
|
|
443
|
+
assert original == restored
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def test_to_dict_roundtrip_no_kind():
|
|
447
|
+
"""测试无 kind 的往返"""
|
|
448
|
+
original = ConnectRef(location="test_loc")
|
|
449
|
+
data = original.to_dict()
|
|
450
|
+
restored = ConnectRef.from_dict(data)
|
|
451
|
+
assert original == restored
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
# =============================================================================
|
|
455
|
+
# ConnectRef Edge Cases
|
|
456
|
+
# =============================================================================
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
def test_special_characters_in_location():
|
|
460
|
+
"""测试 location 中的特殊字符"""
|
|
461
|
+
special_locs = [
|
|
462
|
+
"s3://bucket/key/with/slashes",
|
|
463
|
+
"/local/path/with spaces",
|
|
464
|
+
"~/user/home/path",
|
|
465
|
+
"path\\with\\backslashes",
|
|
466
|
+
"path-with-dashes",
|
|
467
|
+
"path_with_underscores",
|
|
468
|
+
"path.with.dots",
|
|
469
|
+
]
|
|
470
|
+
|
|
471
|
+
for loc in special_locs:
|
|
472
|
+
ref = ConnectRef(location=loc)
|
|
473
|
+
assert ref.location == loc
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def test_unicode_in_location():
|
|
477
|
+
"""测试 location 中的 Unicode 字符"""
|
|
478
|
+
ref = ConnectRef(location="路径/文件.txt", kind="中文")
|
|
479
|
+
assert ref.location == "路径/文件.txt"
|
|
480
|
+
assert ref.kind == "中文"
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
def test_very_long_location():
|
|
484
|
+
"""测试非常长的 location"""
|
|
485
|
+
long_loc = "a" * 10000
|
|
486
|
+
ref = ConnectRef(location=long_loc)
|
|
487
|
+
assert ref.location == long_loc
|
|
488
|
+
assert len(ref.location) == 10000
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def test_empty_string_location():
|
|
492
|
+
"""测试空字符串 location"""
|
|
493
|
+
ref = ConnectRef(location="")
|
|
494
|
+
assert ref.location == ""
|
|
495
|
+
assert str(ref) == ""
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
def test_whitespace_only_location():
|
|
499
|
+
"""测试仅空格的 location"""
|
|
500
|
+
ref = ConnectRef(location=" ")
|
|
501
|
+
assert ref.location == " "
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def test_newline_in_location():
|
|
505
|
+
"""测试 location 中的换行符"""
|
|
506
|
+
ref = ConnectRef(location="line1\nline2")
|
|
507
|
+
assert ref.location == "line1\nline2"
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
# =============================================================================
|
|
511
|
+
# Real-World Usage Tests
|
|
512
|
+
# =============================================================================
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
def test_s3_reference():
|
|
516
|
+
"""测试 S3 引用"""
|
|
517
|
+
ref = ConnectRef(location="s3://my-bucket/path/to/object.parquet", kind="s3")
|
|
518
|
+
assert ref.location == "s3://my-bucket/path/to/object.parquet"
|
|
519
|
+
assert ref.kind == "s3"
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
def test_local_file_reference():
|
|
523
|
+
"""测试本地文件引用"""
|
|
524
|
+
ref = ConnectRef(location="/Users/username/data/file.csv", kind="macos")
|
|
525
|
+
assert ref.location == "/Users/username/data/file.csv"
|
|
526
|
+
assert ref.kind == "macos"
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
def test_relative_path_reference():
|
|
530
|
+
"""测试相对路径引用"""
|
|
531
|
+
ref = ConnectRef(location="./data/file.json", kind="local")
|
|
532
|
+
assert ref.location == "./data/file.json"
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
def test_http_url_reference():
|
|
536
|
+
"""测试 HTTP URL 引用"""
|
|
537
|
+
ref = ConnectRef(location="https://example.com/data/file.json", kind="http")
|
|
538
|
+
assert ref.location == "https://example.com/data/file.json"
|
|
539
|
+
assert ref.kind == "http"
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
def test_multiple_references_in_list():
|
|
543
|
+
"""测试列表中的多个引用"""
|
|
544
|
+
refs = [
|
|
545
|
+
ConnectRef(location="loc1", kind="s3"),
|
|
546
|
+
ConnectRef(location="loc2", kind="macos"),
|
|
547
|
+
ConnectRef(location="loc3", kind="s3"),
|
|
548
|
+
]
|
|
549
|
+
|
|
550
|
+
assert len(refs) == 3
|
|
551
|
+
assert all(isinstance(ref, ConnectRef) for ref in refs)
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
def test_reference_serialization_workflow():
|
|
555
|
+
"""测试引用的序列化工作流"""
|
|
556
|
+
# Create
|
|
557
|
+
ref = ConnectRef(location="s3://bucket/key", kind="s3")
|
|
558
|
+
|
|
559
|
+
# Serialize
|
|
560
|
+
data = ref.to_dict()
|
|
561
|
+
assert isinstance(data, dict)
|
|
562
|
+
|
|
563
|
+
# Store (simulate JSON)
|
|
564
|
+
import json
|
|
565
|
+
|
|
566
|
+
json_str = json.dumps(data)
|
|
567
|
+
|
|
568
|
+
# Restore
|
|
569
|
+
restored_data = json.loads(json_str)
|
|
570
|
+
restored_ref = ConnectRef.from_dict(restored_data)
|
|
571
|
+
|
|
572
|
+
# Verify
|
|
573
|
+
assert restored_ref == ref
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
def test_reference_in_metadata():
|
|
577
|
+
"""测试引用在元数据中的使用"""
|
|
578
|
+
metadata = {
|
|
579
|
+
"source": ConnectRef(location="s3://source/data", kind="s3"),
|
|
580
|
+
"destination": ConnectRef(location="/local/output", kind="macos"),
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
assert isinstance(metadata["source"], ConnectRef)
|
|
584
|
+
assert isinstance(metadata["destination"], ConnectRef)
|
|
585
|
+
assert metadata["source"].kind == "s3"
|
|
586
|
+
assert metadata["destination"].kind == "macos"
|