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,681 @@
|
|
|
1
|
+
import pickle
|
|
2
|
+
import tempfile
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from xfintech.data.common.cache import Cache
|
|
6
|
+
|
|
7
|
+
# ==================== Cache Initialization Tests ====================
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_cache_init_default():
|
|
11
|
+
"""Test Cache initialization with default values"""
|
|
12
|
+
cache = Cache()
|
|
13
|
+
|
|
14
|
+
assert cache.identifier is not None
|
|
15
|
+
assert len(cache.identifier) == 12
|
|
16
|
+
assert cache.path is not None
|
|
17
|
+
assert cache.path.exists()
|
|
18
|
+
assert cache.path.is_dir()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_cache_init_custom_path():
|
|
22
|
+
"""Test Cache initialization with custom path"""
|
|
23
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
24
|
+
custom_path = Path(tmpdir) / "custom_cache"
|
|
25
|
+
cache = Cache(path=custom_path)
|
|
26
|
+
|
|
27
|
+
assert cache.path.parent == custom_path
|
|
28
|
+
assert cache.path.exists()
|
|
29
|
+
assert str(custom_path) in str(cache.path)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_cache_init_creates_directory():
|
|
33
|
+
"""Test Cache creates directory if it doesn't exist"""
|
|
34
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
35
|
+
new_path = Path(tmpdir) / "new" / "nested" / "path"
|
|
36
|
+
cache = Cache(path=new_path)
|
|
37
|
+
|
|
38
|
+
assert cache.path.exists()
|
|
39
|
+
assert cache.path.is_dir()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_cache_unique_identifiers():
|
|
43
|
+
"""Test different Cache instances have unique identifiers"""
|
|
44
|
+
cache1 = Cache()
|
|
45
|
+
cache2 = Cache()
|
|
46
|
+
|
|
47
|
+
assert cache1.identifier != cache2.identifier
|
|
48
|
+
assert cache1.path != cache2.path
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_cache_identifier_format():
|
|
52
|
+
"""Test identifier is 12-character hex string"""
|
|
53
|
+
cache = Cache()
|
|
54
|
+
|
|
55
|
+
assert len(cache.identifier) == 12
|
|
56
|
+
# Should be valid hex
|
|
57
|
+
int(cache.identifier, 16)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# ==================== Resolve Methods Tests ====================
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_cache_resolve_identifier():
|
|
64
|
+
"""Test _resolve_identifier generates valid UUID hex"""
|
|
65
|
+
cache = Cache()
|
|
66
|
+
identifier = cache._resolve_identifier()
|
|
67
|
+
|
|
68
|
+
assert isinstance(identifier, str)
|
|
69
|
+
assert len(identifier) == 12
|
|
70
|
+
# Should be valid hex
|
|
71
|
+
int(identifier, 16)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_cache_resolve_path_with_none():
|
|
75
|
+
"""Test _resolve_path with None uses default"""
|
|
76
|
+
cache = Cache()
|
|
77
|
+
path = cache._resolve_path(None)
|
|
78
|
+
|
|
79
|
+
assert path.exists()
|
|
80
|
+
assert str(Cache.DEFAULT_PARENT) in str(path)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_cache_resolve_path_with_string():
|
|
84
|
+
"""Test _resolve_path with string path"""
|
|
85
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
86
|
+
cache = Cache()
|
|
87
|
+
path = cache._resolve_path(tmpdir)
|
|
88
|
+
|
|
89
|
+
assert path.exists()
|
|
90
|
+
assert str(tmpdir) in str(path)
|
|
91
|
+
assert cache.identifier in str(path)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_cache_resolve_path_with_path_object():
|
|
95
|
+
"""Test _resolve_path with Path object"""
|
|
96
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
97
|
+
cache = Cache()
|
|
98
|
+
path = cache._resolve_path(Path(tmpdir))
|
|
99
|
+
|
|
100
|
+
assert path.exists()
|
|
101
|
+
assert isinstance(path, Path)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# ==================== Get Unit Tests ====================
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def test_cache_get_unit():
|
|
108
|
+
"""Test get_unit returns correct path"""
|
|
109
|
+
cache = Cache()
|
|
110
|
+
unit_path = cache.get_unit("test_key")
|
|
111
|
+
|
|
112
|
+
assert isinstance(unit_path, Path)
|
|
113
|
+
assert unit_path.suffix == ".pkl"
|
|
114
|
+
assert unit_path.parent == cache.path
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def test_cache_get_unit_consistent():
|
|
118
|
+
"""Test get_unit returns same path for same key"""
|
|
119
|
+
cache = Cache()
|
|
120
|
+
|
|
121
|
+
path1 = cache.get_unit("test_key")
|
|
122
|
+
path2 = cache.get_unit("test_key")
|
|
123
|
+
|
|
124
|
+
assert path1 == path2
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def test_cache_get_unit_different_keys():
|
|
128
|
+
"""Test get_unit returns different paths for different keys"""
|
|
129
|
+
cache = Cache()
|
|
130
|
+
|
|
131
|
+
path1 = cache.get_unit("key1")
|
|
132
|
+
path2 = cache.get_unit("key2")
|
|
133
|
+
|
|
134
|
+
assert path1 != path2
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def test_cache_get_unit_uses_md5():
|
|
138
|
+
"""Test get_unit uses MD5 hashing"""
|
|
139
|
+
cache = Cache()
|
|
140
|
+
unit_path = cache.get_unit("test_key")
|
|
141
|
+
|
|
142
|
+
# Verify it's a 32-character hex string (MD5)
|
|
143
|
+
assert len(unit_path.stem) == 32
|
|
144
|
+
int(unit_path.stem, 16)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def test_cache_get_unit_handles_special_characters():
|
|
148
|
+
"""Test get_unit handles special characters in keys"""
|
|
149
|
+
cache = Cache()
|
|
150
|
+
|
|
151
|
+
path1 = cache.get_unit("key with spaces")
|
|
152
|
+
path2 = cache.get_unit("key/with/slashes")
|
|
153
|
+
path3 = cache.get_unit("键中文")
|
|
154
|
+
|
|
155
|
+
assert path1.exists() or not path1.exists() # Should not raise
|
|
156
|
+
assert path2.exists() or not path2.exists()
|
|
157
|
+
assert path3.exists() or not path3.exists()
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# ==================== Contains Tests ====================
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def test_cache_contains_false():
|
|
164
|
+
"""Test __contains__ returns False for non-existent key"""
|
|
165
|
+
cache = Cache()
|
|
166
|
+
|
|
167
|
+
assert "nonexistent" not in cache
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def test_cache_contains_true():
|
|
171
|
+
"""Test __contains__ returns True for existing key"""
|
|
172
|
+
cache = Cache()
|
|
173
|
+
cache.set("test_key", "test_value")
|
|
174
|
+
|
|
175
|
+
assert "test_key" in cache
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def test_cache_contains_after_delete():
|
|
179
|
+
"""Test __contains__ returns False after deletion"""
|
|
180
|
+
cache = Cache()
|
|
181
|
+
cache.set("test_key", "test_value")
|
|
182
|
+
|
|
183
|
+
unit_path = cache.get_unit("test_key")
|
|
184
|
+
unit_path.unlink()
|
|
185
|
+
|
|
186
|
+
assert "test_key" not in cache
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
# ==================== String Representation Tests ====================
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def test_cache_str():
|
|
193
|
+
"""Test __str__ returns path string"""
|
|
194
|
+
cache = Cache()
|
|
195
|
+
|
|
196
|
+
str_repr = str(cache)
|
|
197
|
+
|
|
198
|
+
assert isinstance(str_repr, str)
|
|
199
|
+
assert str(cache.path) == str_repr
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def test_cache_repr():
|
|
203
|
+
"""Test __repr__ returns detailed representation"""
|
|
204
|
+
cache = Cache()
|
|
205
|
+
|
|
206
|
+
repr_str = repr(cache)
|
|
207
|
+
|
|
208
|
+
assert "Cache" in repr_str
|
|
209
|
+
assert "path=" in repr_str
|
|
210
|
+
assert str(cache.path) in repr_str
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
# ==================== Get Tests ====================
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def test_cache_get_nonexistent():
|
|
217
|
+
"""Test get returns None for non-existent key"""
|
|
218
|
+
cache = Cache()
|
|
219
|
+
|
|
220
|
+
result = cache.get("nonexistent")
|
|
221
|
+
|
|
222
|
+
assert result is None
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def test_cache_get_existing():
|
|
226
|
+
"""Test get returns value for existing key"""
|
|
227
|
+
cache = Cache()
|
|
228
|
+
cache.set("test_key", "test_value")
|
|
229
|
+
|
|
230
|
+
result = cache.get("test_key")
|
|
231
|
+
|
|
232
|
+
assert result == "test_value"
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def test_cache_get_with_dict():
|
|
236
|
+
"""Test get works with dictionary values"""
|
|
237
|
+
cache = Cache()
|
|
238
|
+
test_data = {"key": "value", "number": 42}
|
|
239
|
+
cache.set("dict_key", test_data)
|
|
240
|
+
|
|
241
|
+
result = cache.get("dict_key")
|
|
242
|
+
|
|
243
|
+
assert result == test_data
|
|
244
|
+
assert result["key"] == "value"
|
|
245
|
+
assert result["number"] == 42
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def test_cache_get_with_list():
|
|
249
|
+
"""Test get works with list values"""
|
|
250
|
+
cache = Cache()
|
|
251
|
+
test_data = [1, 2, 3, "four", {"five": 5}]
|
|
252
|
+
cache.set("list_key", test_data)
|
|
253
|
+
|
|
254
|
+
result = cache.get("list_key")
|
|
255
|
+
|
|
256
|
+
assert result == test_data
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def test_cache_get_with_none_value():
|
|
260
|
+
"""Test get works with None as value"""
|
|
261
|
+
cache = Cache()
|
|
262
|
+
cache.set("none_key", None)
|
|
263
|
+
|
|
264
|
+
result = cache.get("none_key")
|
|
265
|
+
|
|
266
|
+
# This is tricky - None value vs non-existent key
|
|
267
|
+
# Current implementation will return None for both
|
|
268
|
+
assert result is None
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def test_cache_get_corrupted_file():
|
|
272
|
+
"""Test get returns None for corrupted cache file"""
|
|
273
|
+
cache = Cache()
|
|
274
|
+
unit_path = cache.get_unit("corrupted")
|
|
275
|
+
|
|
276
|
+
# Create corrupted file
|
|
277
|
+
with unit_path.open("w") as f:
|
|
278
|
+
f.write("not valid pickle data")
|
|
279
|
+
|
|
280
|
+
result = cache.get("corrupted")
|
|
281
|
+
|
|
282
|
+
assert result is None
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def test_cache_get_empty_file():
|
|
286
|
+
"""Test get returns None for empty cache file"""
|
|
287
|
+
cache = Cache()
|
|
288
|
+
unit_path = cache.get_unit("empty")
|
|
289
|
+
|
|
290
|
+
# Create empty file
|
|
291
|
+
unit_path.touch()
|
|
292
|
+
|
|
293
|
+
result = cache.get("empty")
|
|
294
|
+
|
|
295
|
+
assert result is None
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
# ==================== Set Tests ====================
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def test_cache_set_basic():
|
|
302
|
+
"""Test set stores value"""
|
|
303
|
+
cache = Cache()
|
|
304
|
+
|
|
305
|
+
cache.set("test_key", "test_value")
|
|
306
|
+
|
|
307
|
+
unit_path = cache.get_unit("test_key")
|
|
308
|
+
assert unit_path.exists()
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def test_cache_set_overwrites():
|
|
312
|
+
"""Test set overwrites existing value"""
|
|
313
|
+
cache = Cache()
|
|
314
|
+
|
|
315
|
+
cache.set("test_key", "first_value")
|
|
316
|
+
cache.set("test_key", "second_value")
|
|
317
|
+
|
|
318
|
+
result = cache.get("test_key")
|
|
319
|
+
assert result == "second_value"
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def test_cache_set_multiple_keys():
|
|
323
|
+
"""Test set works with multiple keys"""
|
|
324
|
+
cache = Cache()
|
|
325
|
+
|
|
326
|
+
cache.set("key1", "value1")
|
|
327
|
+
cache.set("key2", "value2")
|
|
328
|
+
cache.set("key3", "value3")
|
|
329
|
+
|
|
330
|
+
assert cache.get("key1") == "value1"
|
|
331
|
+
assert cache.get("key2") == "value2"
|
|
332
|
+
assert cache.get("key3") == "value3"
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def test_cache_set_complex_objects():
|
|
336
|
+
"""Test set works with complex Python objects"""
|
|
337
|
+
cache = Cache()
|
|
338
|
+
|
|
339
|
+
test_data = {
|
|
340
|
+
"string": "text",
|
|
341
|
+
"number": 42,
|
|
342
|
+
"float": 3.14,
|
|
343
|
+
"list": [1, 2, 3],
|
|
344
|
+
"nested": {"inner": "value"},
|
|
345
|
+
"tuple": (1, 2, 3),
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
cache.set("complex", test_data)
|
|
349
|
+
result = cache.get("complex")
|
|
350
|
+
|
|
351
|
+
assert result == test_data
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def test_cache_set_creates_pickle_file():
|
|
355
|
+
"""Test set creates valid pickle file"""
|
|
356
|
+
cache = Cache()
|
|
357
|
+
|
|
358
|
+
cache.set("test_key", {"data": "value"})
|
|
359
|
+
|
|
360
|
+
unit_path = cache.get_unit("test_key")
|
|
361
|
+
with unit_path.open("rb") as f:
|
|
362
|
+
payload = pickle.load(f)
|
|
363
|
+
|
|
364
|
+
assert "value" in payload
|
|
365
|
+
assert payload["value"] == {"data": "value"}
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# ==================== List Tests ====================
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def test_cache_list_empty():
|
|
372
|
+
"""Test list returns empty list for new cache"""
|
|
373
|
+
cache = Cache()
|
|
374
|
+
|
|
375
|
+
keys = cache.list()
|
|
376
|
+
|
|
377
|
+
assert isinstance(keys, list)
|
|
378
|
+
assert len(keys) == 0
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def test_cache_list_with_items():
|
|
382
|
+
"""Test list returns all cached keys"""
|
|
383
|
+
cache = Cache()
|
|
384
|
+
|
|
385
|
+
cache.set("key1", "value1")
|
|
386
|
+
cache.set("key2", "value2")
|
|
387
|
+
cache.set("key3", "value3")
|
|
388
|
+
|
|
389
|
+
keys = cache.list()
|
|
390
|
+
|
|
391
|
+
assert len(keys) == 3
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def test_cache_list_returns_hashes():
|
|
395
|
+
"""Test list returns MD5 hashes not original keys"""
|
|
396
|
+
cache = Cache()
|
|
397
|
+
|
|
398
|
+
cache.set("original_key", "value")
|
|
399
|
+
|
|
400
|
+
keys = cache.list()
|
|
401
|
+
|
|
402
|
+
assert len(keys) == 1
|
|
403
|
+
# Keys are MD5 hashes (32 hex chars)
|
|
404
|
+
assert len(keys[0]) == 32
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def test_cache_list_after_clear():
|
|
408
|
+
"""Test list returns empty after clear"""
|
|
409
|
+
cache = Cache()
|
|
410
|
+
|
|
411
|
+
cache.set("key1", "value1")
|
|
412
|
+
cache.set("key2", "value2")
|
|
413
|
+
cache.clear()
|
|
414
|
+
|
|
415
|
+
keys = cache.list()
|
|
416
|
+
|
|
417
|
+
assert len(keys) == 0
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
# ==================== Clear Tests ====================
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def test_cache_clear_empty():
|
|
424
|
+
"""Test clear on empty cache doesn't raise error"""
|
|
425
|
+
cache = Cache()
|
|
426
|
+
|
|
427
|
+
cache.clear() # Should not raise
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def test_cache_clear_removes_files():
|
|
431
|
+
"""Test clear removes all cache files"""
|
|
432
|
+
cache = Cache()
|
|
433
|
+
|
|
434
|
+
cache.set("key1", "value1")
|
|
435
|
+
cache.set("key2", "value2")
|
|
436
|
+
|
|
437
|
+
cache.clear()
|
|
438
|
+
|
|
439
|
+
assert len(list(cache.path.glob("*.pkl"))) == 0
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def test_cache_clear_verifies_removal():
|
|
443
|
+
"""Test clear actually removes accessible files"""
|
|
444
|
+
cache = Cache()
|
|
445
|
+
|
|
446
|
+
cache.set("key1", "value1")
|
|
447
|
+
cache.set("key2", "value2")
|
|
448
|
+
|
|
449
|
+
cache.clear()
|
|
450
|
+
|
|
451
|
+
assert cache.get("key1") is None
|
|
452
|
+
assert cache.get("key2") is None
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
def test_cache_clear_handles_errors():
|
|
456
|
+
"""Test clear handles errors gracefully"""
|
|
457
|
+
cache = Cache()
|
|
458
|
+
cache.set("test", "value")
|
|
459
|
+
|
|
460
|
+
# Clear should not raise even if files can't be deleted
|
|
461
|
+
cache.clear() # Should complete without exception
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
# ==================== Describe / To Dict Tests ====================
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def test_cache_describe():
|
|
468
|
+
"""Test describe returns dict"""
|
|
469
|
+
cache = Cache()
|
|
470
|
+
|
|
471
|
+
result = cache.describe()
|
|
472
|
+
|
|
473
|
+
assert isinstance(result, dict)
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def test_cache_describe_equals_to_dict():
|
|
477
|
+
"""Test describe returns same as to_dict"""
|
|
478
|
+
cache = Cache()
|
|
479
|
+
|
|
480
|
+
describe_result = cache.describe()
|
|
481
|
+
to_dict_result = cache.to_dict()
|
|
482
|
+
|
|
483
|
+
assert describe_result == to_dict_result
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
def test_cache_to_dict_structure():
|
|
487
|
+
"""Test to_dict returns expected structure"""
|
|
488
|
+
cache = Cache()
|
|
489
|
+
|
|
490
|
+
result = cache.to_dict()
|
|
491
|
+
|
|
492
|
+
assert "identifier" in result
|
|
493
|
+
assert "path" in result
|
|
494
|
+
assert "units" in result
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
def test_cache_to_dict_values():
|
|
498
|
+
"""Test to_dict returns correct values"""
|
|
499
|
+
cache = Cache()
|
|
500
|
+
|
|
501
|
+
result = cache.to_dict()
|
|
502
|
+
|
|
503
|
+
assert result["identifier"] == cache.identifier
|
|
504
|
+
assert result["path"] == str(cache.path)
|
|
505
|
+
assert isinstance(result["units"], list)
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
def test_cache_to_dict_with_data():
|
|
509
|
+
"""Test to_dict includes cache items"""
|
|
510
|
+
cache = Cache()
|
|
511
|
+
|
|
512
|
+
cache.set("key1", "value1")
|
|
513
|
+
cache.set("key2", "value2")
|
|
514
|
+
|
|
515
|
+
result = cache.to_dict()
|
|
516
|
+
|
|
517
|
+
assert len(result["units"]) == 2
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
# ==================== Integration Tests ====================
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
def test_cache_full_workflow():
|
|
524
|
+
"""Test complete cache workflow"""
|
|
525
|
+
cache = Cache()
|
|
526
|
+
|
|
527
|
+
# Set values
|
|
528
|
+
cache.set("user", {"name": "张三", "age": 30})
|
|
529
|
+
cache.set("items", [1, 2, 3, 4, 5])
|
|
530
|
+
|
|
531
|
+
# Check existence
|
|
532
|
+
assert "user" in cache
|
|
533
|
+
assert "items" in cache
|
|
534
|
+
assert "nonexistent" not in cache
|
|
535
|
+
|
|
536
|
+
# Get values
|
|
537
|
+
user = cache.get("user")
|
|
538
|
+
items = cache.get("items")
|
|
539
|
+
|
|
540
|
+
assert user["name"] == "张三"
|
|
541
|
+
assert len(items) == 5
|
|
542
|
+
|
|
543
|
+
# List keys
|
|
544
|
+
keys = cache.list()
|
|
545
|
+
assert len(keys) == 2
|
|
546
|
+
|
|
547
|
+
# Get info
|
|
548
|
+
info = cache.to_dict()
|
|
549
|
+
assert len(info["units"]) == 2
|
|
550
|
+
|
|
551
|
+
# Clear
|
|
552
|
+
cache.clear()
|
|
553
|
+
assert len(cache.list()) == 0
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
def test_cache_persistence():
|
|
557
|
+
"""Test cache persists across instances with same path"""
|
|
558
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
559
|
+
custom_path = Path(tmpdir)
|
|
560
|
+
|
|
561
|
+
# Create cache and set value
|
|
562
|
+
cache1 = Cache(path=custom_path)
|
|
563
|
+
identifier1 = cache1.identifier
|
|
564
|
+
cache1.set("persist_key", "persist_value")
|
|
565
|
+
|
|
566
|
+
# Create new cache with same base path
|
|
567
|
+
cache2 = Cache(path=custom_path / identifier1)
|
|
568
|
+
cache2.get("persist_key")
|
|
569
|
+
|
|
570
|
+
# Note: This won't work because each Cache gets unique identifier
|
|
571
|
+
# But the files exist in the directory
|
|
572
|
+
assert len(list((custom_path / identifier1).glob("*.pkl"))) > 0
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
def test_cache_isolation():
|
|
576
|
+
"""Test different caches are isolated"""
|
|
577
|
+
cache1 = Cache()
|
|
578
|
+
cache2 = Cache()
|
|
579
|
+
|
|
580
|
+
cache1.set("key", "value1")
|
|
581
|
+
cache2.set("key", "value2")
|
|
582
|
+
|
|
583
|
+
assert cache1.get("key") == "value1"
|
|
584
|
+
assert cache2.get("key") == "value2"
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
def test_cache_handles_concurrent_operations():
|
|
588
|
+
"""Test cache handles multiple operations in sequence"""
|
|
589
|
+
cache = Cache()
|
|
590
|
+
|
|
591
|
+
# Rapid set/get operations
|
|
592
|
+
for i in range(10):
|
|
593
|
+
cache.set(f"key{i}", f"value{i}")
|
|
594
|
+
|
|
595
|
+
# Verify all stored
|
|
596
|
+
for i in range(10):
|
|
597
|
+
assert cache.get(f"key{i}") == f"value{i}"
|
|
598
|
+
|
|
599
|
+
# List should have all
|
|
600
|
+
assert len(cache.list()) == 10
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
def test_cache_large_value():
|
|
604
|
+
"""Test cache handles large values"""
|
|
605
|
+
cache = Cache()
|
|
606
|
+
|
|
607
|
+
# Large list
|
|
608
|
+
large_data = list(range(10000))
|
|
609
|
+
cache.set("large", large_data)
|
|
610
|
+
|
|
611
|
+
result = cache.get("large")
|
|
612
|
+
|
|
613
|
+
assert len(result) == 10000
|
|
614
|
+
assert result[0] == 0
|
|
615
|
+
assert result[-1] == 9999
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
def test_cache_unicode_keys():
|
|
619
|
+
"""Test cache handles unicode in keys"""
|
|
620
|
+
cache = Cache()
|
|
621
|
+
|
|
622
|
+
cache.set("中文键", "中文值")
|
|
623
|
+
cache.set("🔑emoji", "😀emoji_value")
|
|
624
|
+
|
|
625
|
+
assert cache.get("中文键") == "中文值"
|
|
626
|
+
assert cache.get("🔑emoji") == "😀emoji_value"
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
def test_cache_update_value():
|
|
630
|
+
"""Test updating cached value multiple times"""
|
|
631
|
+
cache = Cache()
|
|
632
|
+
|
|
633
|
+
cache.set("counter", 0)
|
|
634
|
+
|
|
635
|
+
for i in range(1, 6):
|
|
636
|
+
cache.set("counter", i)
|
|
637
|
+
|
|
638
|
+
result = cache.get("counter")
|
|
639
|
+
assert result == 5
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
def test_cache_binary_data():
|
|
643
|
+
"""Test cache handles binary data"""
|
|
644
|
+
cache = Cache()
|
|
645
|
+
|
|
646
|
+
binary_data = b"\x00\x01\x02\x03\x04\x05"
|
|
647
|
+
cache.set("binary", binary_data)
|
|
648
|
+
|
|
649
|
+
result = cache.get("binary")
|
|
650
|
+
assert result == binary_data
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
def test_cache_nested_structures():
|
|
654
|
+
"""Test cache handles deeply nested structures"""
|
|
655
|
+
cache = Cache()
|
|
656
|
+
|
|
657
|
+
nested = {"level1": {"level2": {"level3": {"level4": {"data": [1, 2, 3]}}}}}
|
|
658
|
+
|
|
659
|
+
cache.set("nested", nested)
|
|
660
|
+
result = cache.get("nested")
|
|
661
|
+
|
|
662
|
+
assert result["level1"]["level2"]["level3"]["level4"]["data"] == [1, 2, 3]
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
def test_cache_custom_path_cleanup():
|
|
666
|
+
"""Test cache with custom path cleans up properly"""
|
|
667
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
668
|
+
custom_path = Path(tmpdir) / "test_cache"
|
|
669
|
+
cache = Cache(path=custom_path)
|
|
670
|
+
|
|
671
|
+
cache.set("key1", "value1")
|
|
672
|
+
cache.set("key2", "value2")
|
|
673
|
+
|
|
674
|
+
# Verify files created
|
|
675
|
+
assert len(list(cache.path.glob("*.pkl"))) == 2
|
|
676
|
+
|
|
677
|
+
# Clear
|
|
678
|
+
cache.clear()
|
|
679
|
+
|
|
680
|
+
# Verify files removed
|
|
681
|
+
assert len(list(cache.path.glob("*.pkl"))) == 0
|