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,547 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from xfintech.fabric.column.info import ColumnInfo
|
|
4
|
+
from xfintech.fabric.column.kind import ColumnKind
|
|
5
|
+
from xfintech.fabric.table.info import TableInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_tableinfo_basic_init():
|
|
9
|
+
table = TableInfo(
|
|
10
|
+
name="daily_market",
|
|
11
|
+
desc=" 日线行情表 ",
|
|
12
|
+
meta={"source": "tushare"},
|
|
13
|
+
columns=[
|
|
14
|
+
ColumnInfo(name="price", kind="Float", desc="收盘价"),
|
|
15
|
+
ColumnInfo(name="volume", kind="Integer", desc="成交量"),
|
|
16
|
+
],
|
|
17
|
+
)
|
|
18
|
+
assert table.name == "daily_market"
|
|
19
|
+
assert table.desc == "日线行情表"
|
|
20
|
+
assert table.meta == {"source": "tushare"}
|
|
21
|
+
assert len(table.columns) == 2
|
|
22
|
+
assert "price" in table.columns
|
|
23
|
+
assert "volume" in table.columns
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_tableinfo_name_must_be_valid():
|
|
27
|
+
with pytest.raises(ValueError):
|
|
28
|
+
TableInfo(name="1invalid")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_tableinfo_name_is_lowercase():
|
|
32
|
+
table = TableInfo(name="MyTable")
|
|
33
|
+
assert table.name == "mytable"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_tableinfo_name_empty_when_none():
|
|
37
|
+
table = TableInfo(name=None)
|
|
38
|
+
assert table.name == ""
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_tableinfo_name_accepts_underscore_hyphen():
|
|
42
|
+
table1 = TableInfo(name="my_table")
|
|
43
|
+
assert table1.name == "my_table"
|
|
44
|
+
|
|
45
|
+
table2 = TableInfo(name="my-table")
|
|
46
|
+
assert table2.name == "my-table"
|
|
47
|
+
|
|
48
|
+
table3 = TableInfo(name="_private_table")
|
|
49
|
+
assert table3.name == "_private_table"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_tableinfo_desc_strip():
|
|
53
|
+
table = TableInfo(
|
|
54
|
+
name="test",
|
|
55
|
+
desc=" Something Here ",
|
|
56
|
+
)
|
|
57
|
+
assert table.desc == "Something Here"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_tableinfo_desc_empty_when_none():
|
|
61
|
+
table = TableInfo(name="test", desc=None)
|
|
62
|
+
assert table.desc == ""
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_tableinfo_meta_bytes_to_str():
|
|
66
|
+
table = TableInfo(
|
|
67
|
+
name="test",
|
|
68
|
+
meta={
|
|
69
|
+
b"bin": b"yes",
|
|
70
|
+
"code": b"ok",
|
|
71
|
+
},
|
|
72
|
+
)
|
|
73
|
+
assert table.meta == {"bin": "yes", "code": "ok"}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_tableinfo_meta_str_normal():
|
|
77
|
+
table = TableInfo(name="test", meta={"x": 1, "y": "value"})
|
|
78
|
+
assert table.meta == {"x": 1, "y": "value"}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_tableinfo_meta_none():
|
|
82
|
+
table = TableInfo(name="test", meta=None)
|
|
83
|
+
assert table.meta is None
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_tableinfo_columns_from_columninfo_list():
|
|
87
|
+
table = TableInfo(
|
|
88
|
+
name="test",
|
|
89
|
+
columns=[
|
|
90
|
+
ColumnInfo(name="price", kind="Float"),
|
|
91
|
+
ColumnInfo(name="volume", kind="Integer"),
|
|
92
|
+
],
|
|
93
|
+
)
|
|
94
|
+
assert len(table.columns) == 2
|
|
95
|
+
assert table.columns["price"].kind == ColumnKind.FLOAT
|
|
96
|
+
assert table.columns["volume"].kind == ColumnKind.INTEGER
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def test_tableinfo_columns_from_dict_list():
|
|
100
|
+
table = TableInfo(
|
|
101
|
+
name="test",
|
|
102
|
+
columns=[
|
|
103
|
+
{"name": "price", "kind": "Float"},
|
|
104
|
+
{"name": "volume", "kind": "Integer"},
|
|
105
|
+
],
|
|
106
|
+
)
|
|
107
|
+
assert len(table.columns) == 2
|
|
108
|
+
assert table.columns["price"].kind == ColumnKind.FLOAT
|
|
109
|
+
assert table.columns["volume"].kind == ColumnKind.INTEGER
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def test_tableinfo_columns_mixed_types():
|
|
113
|
+
table = TableInfo(
|
|
114
|
+
name="test",
|
|
115
|
+
columns=[
|
|
116
|
+
ColumnInfo(name="price", kind="Float"),
|
|
117
|
+
{"name": "volume", "kind": "Integer"},
|
|
118
|
+
],
|
|
119
|
+
)
|
|
120
|
+
assert len(table.columns) == 2
|
|
121
|
+
assert isinstance(table.columns["price"], ColumnInfo)
|
|
122
|
+
assert isinstance(table.columns["volume"], ColumnInfo)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def test_tableinfo_columns_invalid_type():
|
|
126
|
+
with pytest.raises(TypeError):
|
|
127
|
+
TableInfo(
|
|
128
|
+
name="test",
|
|
129
|
+
columns=["invalid"],
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_tableinfo_columns_none():
|
|
134
|
+
table = TableInfo(name="test", columns=None)
|
|
135
|
+
assert table.columns == {}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def test_tableinfo_get_column():
|
|
139
|
+
table = TableInfo(
|
|
140
|
+
name="test",
|
|
141
|
+
columns=[
|
|
142
|
+
ColumnInfo(name="price", kind="Float"),
|
|
143
|
+
ColumnInfo(name="volume", kind="Integer"),
|
|
144
|
+
],
|
|
145
|
+
)
|
|
146
|
+
col = table.get_column("price")
|
|
147
|
+
assert col is not None
|
|
148
|
+
assert col.name == "price"
|
|
149
|
+
assert col.kind == ColumnKind.FLOAT
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def test_tableinfo_get_column_case_insensitive():
|
|
153
|
+
table = TableInfo(
|
|
154
|
+
name="test",
|
|
155
|
+
columns=[
|
|
156
|
+
ColumnInfo(name="price", kind="Float"),
|
|
157
|
+
],
|
|
158
|
+
)
|
|
159
|
+
col = table.get_column("PRICE")
|
|
160
|
+
assert col is not None
|
|
161
|
+
assert col.name == "price"
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def test_tableinfo_get_column_not_exists():
|
|
165
|
+
table = TableInfo(name="test", columns=[])
|
|
166
|
+
col = table.get_column("nonexistent")
|
|
167
|
+
assert col is None
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def test_tableinfo_add_column():
|
|
171
|
+
table = TableInfo(name="test")
|
|
172
|
+
table.add_column(ColumnInfo(name="price", kind="Float"))
|
|
173
|
+
|
|
174
|
+
assert len(table.columns) == 1
|
|
175
|
+
assert "price" in table.columns
|
|
176
|
+
assert table.columns["price"].kind == ColumnKind.FLOAT
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def test_tableinfo_add_column_from_dict():
|
|
180
|
+
table = TableInfo(name="test")
|
|
181
|
+
table.add_column({"name": "price", "kind": "Float"})
|
|
182
|
+
|
|
183
|
+
assert len(table.columns) == 1
|
|
184
|
+
assert "price" in table.columns
|
|
185
|
+
assert table.columns["price"].kind == ColumnKind.FLOAT
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def test_tableinfo_remove_column():
|
|
189
|
+
table = TableInfo(
|
|
190
|
+
name="test",
|
|
191
|
+
columns=[
|
|
192
|
+
ColumnInfo(name="price", kind="Float"),
|
|
193
|
+
ColumnInfo(name="volume", kind="Integer"),
|
|
194
|
+
],
|
|
195
|
+
)
|
|
196
|
+
table.remove_column("price")
|
|
197
|
+
|
|
198
|
+
assert len(table.columns) == 1
|
|
199
|
+
assert "price" not in table.columns
|
|
200
|
+
assert "volume" in table.columns
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def test_tableinfo_remove_column_case_insensitive():
|
|
204
|
+
table = TableInfo(
|
|
205
|
+
name="test",
|
|
206
|
+
columns=[
|
|
207
|
+
ColumnInfo(name="price", kind="Float"),
|
|
208
|
+
],
|
|
209
|
+
)
|
|
210
|
+
table.remove_column("PRICE")
|
|
211
|
+
|
|
212
|
+
assert len(table.columns) == 0
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def test_tableinfo_remove_column_not_exists():
|
|
216
|
+
table = TableInfo(
|
|
217
|
+
name="test",
|
|
218
|
+
columns=[
|
|
219
|
+
ColumnInfo(name="price", kind="Float"),
|
|
220
|
+
],
|
|
221
|
+
)
|
|
222
|
+
table.remove_column("nonexistent")
|
|
223
|
+
|
|
224
|
+
assert len(table.columns) == 1
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def test_tableinfo_update_column_kind_desc_meta():
|
|
228
|
+
table = TableInfo(
|
|
229
|
+
name="test",
|
|
230
|
+
columns=[
|
|
231
|
+
ColumnInfo(
|
|
232
|
+
name="price",
|
|
233
|
+
kind="Float",
|
|
234
|
+
desc="old",
|
|
235
|
+
meta={"unit": "CNY"},
|
|
236
|
+
),
|
|
237
|
+
],
|
|
238
|
+
)
|
|
239
|
+
table.update_column(
|
|
240
|
+
"price",
|
|
241
|
+
kind="Integer",
|
|
242
|
+
desc="new-desc",
|
|
243
|
+
meta={"precision": 2},
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
col = table.get_column("price")
|
|
247
|
+
assert col.kind == ColumnKind.INTEGER
|
|
248
|
+
assert col.desc == "new-desc"
|
|
249
|
+
assert col.meta == {"unit": "CNY", "precision": 2}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def test_tableinfo_update_column_rename():
|
|
253
|
+
table = TableInfo(
|
|
254
|
+
name="test",
|
|
255
|
+
columns=[
|
|
256
|
+
ColumnInfo(name="price", kind="Float"),
|
|
257
|
+
],
|
|
258
|
+
)
|
|
259
|
+
table.update_column("price", new="new_price")
|
|
260
|
+
|
|
261
|
+
assert "price" not in table.columns
|
|
262
|
+
assert "new_price" in table.columns
|
|
263
|
+
assert table.columns["new_price"].kind == ColumnKind.FLOAT
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def test_tableinfo_update_column_not_exists():
|
|
267
|
+
table = TableInfo(
|
|
268
|
+
name="test",
|
|
269
|
+
columns=[
|
|
270
|
+
ColumnInfo(name="price", kind="Float"),
|
|
271
|
+
],
|
|
272
|
+
)
|
|
273
|
+
table.update_column("nonexistent", desc="new")
|
|
274
|
+
|
|
275
|
+
assert len(table.columns) == 1
|
|
276
|
+
assert table.columns["price"].desc == ""
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def test_tableinfo_rename_column():
|
|
280
|
+
table = TableInfo(
|
|
281
|
+
name="test",
|
|
282
|
+
columns=[
|
|
283
|
+
ColumnInfo(name="old_name", kind="Float"),
|
|
284
|
+
],
|
|
285
|
+
)
|
|
286
|
+
table.rename_column("old_name", "new_name")
|
|
287
|
+
|
|
288
|
+
assert "old_name" not in table.columns
|
|
289
|
+
assert "new_name" in table.columns
|
|
290
|
+
assert table.columns["new_name"].name == "new_name"
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def test_tableinfo_rename_column_case_insensitive():
|
|
294
|
+
table = TableInfo(
|
|
295
|
+
name="test",
|
|
296
|
+
columns=[
|
|
297
|
+
ColumnInfo(name="old_name", kind="Float"),
|
|
298
|
+
],
|
|
299
|
+
)
|
|
300
|
+
table.rename_column("OLD_NAME", "new_name")
|
|
301
|
+
|
|
302
|
+
assert "old_name" not in table.columns
|
|
303
|
+
assert "new_name" in table.columns
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def test_tableinfo_rename_column_not_exists():
|
|
307
|
+
table = TableInfo(
|
|
308
|
+
name="test",
|
|
309
|
+
columns=[
|
|
310
|
+
ColumnInfo(name="price", kind="Float"),
|
|
311
|
+
],
|
|
312
|
+
)
|
|
313
|
+
table.rename_column("nonexistent", "new_name")
|
|
314
|
+
|
|
315
|
+
assert len(table.columns) == 1
|
|
316
|
+
assert "new_name" not in table.columns
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def test_tableinfo_list_columns():
|
|
320
|
+
table = TableInfo(
|
|
321
|
+
name="test",
|
|
322
|
+
columns=[
|
|
323
|
+
ColumnInfo(name="price", kind="Float"),
|
|
324
|
+
ColumnInfo(name="volume", kind="Integer"),
|
|
325
|
+
],
|
|
326
|
+
)
|
|
327
|
+
cols = table.list_columns()
|
|
328
|
+
|
|
329
|
+
assert len(cols) == 2
|
|
330
|
+
assert all(isinstance(c, ColumnInfo) for c in cols)
|
|
331
|
+
names = [c.name for c in cols]
|
|
332
|
+
assert "price" in names
|
|
333
|
+
assert "volume" in names
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def test_tableinfo_list_columns_empty():
|
|
337
|
+
table = TableInfo(name="test")
|
|
338
|
+
cols = table.list_columns()
|
|
339
|
+
|
|
340
|
+
assert cols == []
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def test_tableinfo_full_describe():
|
|
344
|
+
table = TableInfo(
|
|
345
|
+
name="test",
|
|
346
|
+
desc="Test table",
|
|
347
|
+
meta={"source": "tushare"},
|
|
348
|
+
columns=[
|
|
349
|
+
ColumnInfo(name="price", kind="Float", desc="Price"),
|
|
350
|
+
],
|
|
351
|
+
)
|
|
352
|
+
d = table.describe()
|
|
353
|
+
|
|
354
|
+
assert d["name"] == "test"
|
|
355
|
+
assert d["desc"] == "Test table"
|
|
356
|
+
assert d["meta"] == {"source": "tushare"}
|
|
357
|
+
assert len(d["columns"]) == 1
|
|
358
|
+
assert d["columns"][0]["name"] == "price"
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def test_tableinfo_partial_describe():
|
|
362
|
+
table = TableInfo(name="test")
|
|
363
|
+
d = table.describe()
|
|
364
|
+
assert "name" in d
|
|
365
|
+
assert "desc" not in d
|
|
366
|
+
assert "meta" not in d
|
|
367
|
+
assert "columns" not in d
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def test_tableinfo_full_to_dict():
|
|
371
|
+
table = TableInfo(
|
|
372
|
+
name="test",
|
|
373
|
+
desc="Test table",
|
|
374
|
+
meta={"source": "tushare"},
|
|
375
|
+
columns=[
|
|
376
|
+
ColumnInfo(name="price", kind="Float", desc="Price"),
|
|
377
|
+
],
|
|
378
|
+
)
|
|
379
|
+
d = table.to_dict()
|
|
380
|
+
|
|
381
|
+
assert "identifier" in d
|
|
382
|
+
assert d["name"] == "test"
|
|
383
|
+
assert d["desc"] == "Test table"
|
|
384
|
+
assert d["meta"] == {"source": "tushare"}
|
|
385
|
+
assert len(d["columns"]) == 1
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def test_tableinfo_from_dict():
|
|
389
|
+
data = {
|
|
390
|
+
"name": "test",
|
|
391
|
+
"desc": "Test table",
|
|
392
|
+
"meta": {"source": "tushare"},
|
|
393
|
+
"columns": [
|
|
394
|
+
{"name": "price", "kind": "Float"},
|
|
395
|
+
{"name": "volume", "kind": "Integer"},
|
|
396
|
+
],
|
|
397
|
+
}
|
|
398
|
+
table = TableInfo.from_dict(data)
|
|
399
|
+
|
|
400
|
+
assert table.name == "test"
|
|
401
|
+
assert table.desc == "Test table"
|
|
402
|
+
assert table.meta == {"source": "tushare"}
|
|
403
|
+
assert len(table.columns) == 2
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def test_tableinfo_from_dict_minimal():
|
|
407
|
+
data = {}
|
|
408
|
+
table = TableInfo.from_dict(data)
|
|
409
|
+
|
|
410
|
+
assert table.name == ""
|
|
411
|
+
assert table.desc == ""
|
|
412
|
+
assert table.meta is None
|
|
413
|
+
assert table.columns == {}
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def test_tableinfo_str():
|
|
417
|
+
table = TableInfo(
|
|
418
|
+
name="test",
|
|
419
|
+
columns=[
|
|
420
|
+
ColumnInfo(name="price", kind="Float"),
|
|
421
|
+
],
|
|
422
|
+
)
|
|
423
|
+
s = str(table)
|
|
424
|
+
assert "price" in s
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def test_tableinfo_repr():
|
|
428
|
+
table = TableInfo(name="test")
|
|
429
|
+
r = repr(table)
|
|
430
|
+
assert "TableInfo" in r
|
|
431
|
+
assert "test" in r
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def test_tableinfo_identifier_is_deterministic():
|
|
435
|
+
table1 = TableInfo(
|
|
436
|
+
name="test",
|
|
437
|
+
desc="Test table",
|
|
438
|
+
meta={"source": "tushare"},
|
|
439
|
+
columns=[
|
|
440
|
+
ColumnInfo(name="price", kind="Float"),
|
|
441
|
+
ColumnInfo(name="volume", kind="Integer"),
|
|
442
|
+
],
|
|
443
|
+
)
|
|
444
|
+
table2 = TableInfo(
|
|
445
|
+
name="test",
|
|
446
|
+
desc="Test table",
|
|
447
|
+
meta={"source": "tushare"},
|
|
448
|
+
columns=[
|
|
449
|
+
ColumnInfo(name="price", kind="Float"),
|
|
450
|
+
ColumnInfo(name="volume", kind="Integer"),
|
|
451
|
+
],
|
|
452
|
+
)
|
|
453
|
+
assert table1.identifier == table2.identifier
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
def test_tableinfo_identifier_not_change_with_meta():
|
|
457
|
+
table1 = TableInfo(
|
|
458
|
+
name="test",
|
|
459
|
+
desc="Test table",
|
|
460
|
+
meta={"source": "tushare"},
|
|
461
|
+
columns=[
|
|
462
|
+
ColumnInfo(name="price", kind="Float"),
|
|
463
|
+
],
|
|
464
|
+
)
|
|
465
|
+
table2 = TableInfo(
|
|
466
|
+
name="test",
|
|
467
|
+
desc="Test table",
|
|
468
|
+
meta={"source": "yahoo"},
|
|
469
|
+
columns=[
|
|
470
|
+
ColumnInfo(name="price", kind="Float"),
|
|
471
|
+
],
|
|
472
|
+
)
|
|
473
|
+
assert table1.identifier == table2.identifier
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def test_tableinfo_identifier_changes_with_name():
|
|
477
|
+
table1 = TableInfo(
|
|
478
|
+
name="test1",
|
|
479
|
+
desc="Test table",
|
|
480
|
+
columns=[
|
|
481
|
+
ColumnInfo(name="price", kind="Float"),
|
|
482
|
+
],
|
|
483
|
+
)
|
|
484
|
+
table2 = TableInfo(
|
|
485
|
+
name="test2",
|
|
486
|
+
desc="Test table",
|
|
487
|
+
columns=[
|
|
488
|
+
ColumnInfo(name="price", kind="Float"),
|
|
489
|
+
],
|
|
490
|
+
)
|
|
491
|
+
assert table1.identifier != table2.identifier
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def test_tableinfo_identifier_changes_with_desc():
|
|
495
|
+
table1 = TableInfo(
|
|
496
|
+
name="test",
|
|
497
|
+
desc="Desc1",
|
|
498
|
+
columns=[
|
|
499
|
+
ColumnInfo(name="price", kind="Float"),
|
|
500
|
+
],
|
|
501
|
+
)
|
|
502
|
+
table2 = TableInfo(
|
|
503
|
+
name="test",
|
|
504
|
+
desc="Desc2",
|
|
505
|
+
columns=[
|
|
506
|
+
ColumnInfo(name="price", kind="Float"),
|
|
507
|
+
],
|
|
508
|
+
)
|
|
509
|
+
assert table1.identifier != table2.identifier
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
def test_tableinfo_identifier_changes_with_columns():
|
|
513
|
+
table1 = TableInfo(
|
|
514
|
+
name="test",
|
|
515
|
+
desc="Test table",
|
|
516
|
+
columns=[
|
|
517
|
+
ColumnInfo(name="price", kind="Float"),
|
|
518
|
+
],
|
|
519
|
+
)
|
|
520
|
+
table2 = TableInfo(
|
|
521
|
+
name="test",
|
|
522
|
+
desc="Test table",
|
|
523
|
+
columns=[
|
|
524
|
+
ColumnInfo(name="volume", kind="Integer"),
|
|
525
|
+
],
|
|
526
|
+
)
|
|
527
|
+
assert table1.identifier != table2.identifier
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
def test_tableinfo_identifier_column_order_independent():
|
|
531
|
+
table1 = TableInfo(
|
|
532
|
+
name="test",
|
|
533
|
+
desc="Test table",
|
|
534
|
+
columns=[
|
|
535
|
+
ColumnInfo(name="price", kind="Float"),
|
|
536
|
+
ColumnInfo(name="volume", kind="Integer"),
|
|
537
|
+
],
|
|
538
|
+
)
|
|
539
|
+
table2 = TableInfo(
|
|
540
|
+
name="test",
|
|
541
|
+
desc="Test table",
|
|
542
|
+
columns=[
|
|
543
|
+
ColumnInfo(name="volume", kind="Integer"),
|
|
544
|
+
ColumnInfo(name="price", kind="Float"),
|
|
545
|
+
],
|
|
546
|
+
)
|
|
547
|
+
assert table1.identifier == table2.identifier
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from .common.dataformat import DataFormat
|
|
2
|
+
from .common.deserialiserlike import DeserialiserLike
|
|
3
|
+
from .common.error import (
|
|
4
|
+
DeserialiserFailedError,
|
|
5
|
+
DeserialiserImportError,
|
|
6
|
+
DeserialiserInputTypeError,
|
|
7
|
+
DeserialiserNotSupportedError,
|
|
8
|
+
SerialiserFailedError,
|
|
9
|
+
SerialiserImportError,
|
|
10
|
+
SerialiserInputTypeError,
|
|
11
|
+
SerialiserNotSupportedError,
|
|
12
|
+
)
|
|
13
|
+
from .common.serialiserlike import SerialiserLike
|
|
14
|
+
from .deserialiser.pandas import PandasDeserialiser
|
|
15
|
+
from .deserialiser.python import PythonDeserialiser
|
|
16
|
+
from .serialiser.pandas import PandasSerialiser
|
|
17
|
+
from .serialiser.python import PythonSerialiser
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"DataFormat",
|
|
21
|
+
"DeserialiserLike",
|
|
22
|
+
"SerialiserLike",
|
|
23
|
+
"PandasDeserialiser",
|
|
24
|
+
"PythonDeserialiser",
|
|
25
|
+
"PandasSerialiser",
|
|
26
|
+
"PythonSerialiser",
|
|
27
|
+
"DeserialiserFailedError",
|
|
28
|
+
"DeserialiserImportError",
|
|
29
|
+
"DeserialiserInputTypeError",
|
|
30
|
+
"DeserialiserNotSupportedError",
|
|
31
|
+
"SerialiserFailedError",
|
|
32
|
+
"SerialiserImportError",
|
|
33
|
+
"SerialiserInputTypeError",
|
|
34
|
+
"SerialiserNotSupportedError",
|
|
35
|
+
]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DataFormat(str, Enum):
|
|
7
|
+
"""
|
|
8
|
+
描述:
|
|
9
|
+
- 序列化和反序列化格式枚举类。
|
|
10
|
+
- 定义支持的数据格式:Parquet、CSV 和 JSON。
|
|
11
|
+
- 继承自 str 和 Enum,可以直接与字符串比较。
|
|
12
|
+
|
|
13
|
+
属性:
|
|
14
|
+
- PARQUET: Parquet 格式 ("parquet")
|
|
15
|
+
- CSV: CSV 格式 ("csv")
|
|
16
|
+
- JSON: JSON 格式 ("json")
|
|
17
|
+
|
|
18
|
+
方法:
|
|
19
|
+
- from_str(string): 从字符串创建 DataFormat 实例(不区分大小写)。
|
|
20
|
+
- from_any(value): 从 DataFormat 实例或字符串创建 DataFormat 实例。
|
|
21
|
+
- list_all(): 列出所有支持的 DataFormat 实例。
|
|
22
|
+
- __str__(): 返回格式的字符串值。
|
|
23
|
+
- __repr__(): 返回格式的表示形式。
|
|
24
|
+
|
|
25
|
+
例子:
|
|
26
|
+
```python
|
|
27
|
+
from xfintech.serde.common.dataformat import DataFormat
|
|
28
|
+
|
|
29
|
+
# 使用枚举值
|
|
30
|
+
fmt = DataFormat.PARQUET
|
|
31
|
+
print(fmt) # parquet
|
|
32
|
+
print(repr(fmt)) # DataFormat.PARQUET
|
|
33
|
+
|
|
34
|
+
# 从字符串创建(不区分大小写)
|
|
35
|
+
fmt = DataFormat.from_str("csv")
|
|
36
|
+
print(fmt) # csv
|
|
37
|
+
|
|
38
|
+
fmt = DataFormat.from_str("JSON")
|
|
39
|
+
print(fmt) # json
|
|
40
|
+
|
|
41
|
+
# 字符串比较
|
|
42
|
+
if DataFormat.PARQUET == "parquet":
|
|
43
|
+
print("Matched!") # 输出: Matched!
|
|
44
|
+
|
|
45
|
+
# 无效格式会抛出 ValueError
|
|
46
|
+
try:
|
|
47
|
+
DataFormat.from_str("xml")
|
|
48
|
+
except ValueError as e:
|
|
49
|
+
print(f"Error: {e}") # Error: Unknown DataFormat: xml
|
|
50
|
+
```
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
PARQUET = "parquet"
|
|
54
|
+
CSV = "csv"
|
|
55
|
+
JSON = "json"
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def from_str(cls, value: str) -> DataFormat:
|
|
59
|
+
for fmt in DataFormat:
|
|
60
|
+
if fmt.value.lower() == value.lower():
|
|
61
|
+
return fmt
|
|
62
|
+
raise ValueError(f"Unknown DataFormat: {value}")
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def from_any(cls, value: DataFormat | str) -> DataFormat:
|
|
66
|
+
if isinstance(value, DataFormat):
|
|
67
|
+
return value
|
|
68
|
+
return cls.from_str(value)
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def list_all(cls) -> list[DataFormat]:
|
|
72
|
+
return [fmt for fmt in cls]
|
|
73
|
+
|
|
74
|
+
def __str__(self) -> str:
|
|
75
|
+
return self.value
|
|
76
|
+
|
|
77
|
+
def __repr__(self) -> str:
|
|
78
|
+
return f"{self.__class__.__name__}.{self.name}"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Protocol, runtime_checkable
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@runtime_checkable
|
|
7
|
+
class DeserialiserLike(Protocol):
|
|
8
|
+
"""
|
|
9
|
+
描述:
|
|
10
|
+
- 通用反序列化接口协议。
|
|
11
|
+
- 定义反序列化方法的签名,适用于各种数据格式。
|
|
12
|
+
- 将字节流转换为数据对象(如 DataFrame)。
|
|
13
|
+
|
|
14
|
+
方法:
|
|
15
|
+
- deserialise(data, format, **kwargs): 通用反序列化方法,返回数据对象。
|
|
16
|
+
|
|
17
|
+
例子:
|
|
18
|
+
```python
|
|
19
|
+
from xfintech.serde.common.deserialiserlike import DeserialiserLike
|
|
20
|
+
import pandas as pd
|
|
21
|
+
|
|
22
|
+
class MyDeserialiser:
|
|
23
|
+
@staticmethod
|
|
24
|
+
def deserialise(data, format, **kwargs):
|
|
25
|
+
# 实现反序列化逻辑
|
|
26
|
+
return pd.DataFrame()
|
|
27
|
+
|
|
28
|
+
# 检查是否符合协议
|
|
29
|
+
assert isinstance(MyDeserialiser(), DeserialiserLike)
|
|
30
|
+
```
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def deserialise(
|
|
35
|
+
data: Any,
|
|
36
|
+
format: Any,
|
|
37
|
+
**kwargs: Any,
|
|
38
|
+
) -> Any: ...
|