dycw-utilities 0.110.2__tar.gz → 0.110.4__tar.gz
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.
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/PKG-INFO +1 -1
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/pyproject.toml +2 -2
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_dataclasses.py +97 -64
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_orjson.py +1 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_parse.py +46 -26
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_text.py +11 -2
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_typing_funcs/with_future.py +16 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/__init__.py +1 -1
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/dataclasses.py +42 -17
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/parse.py +62 -9
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/text.py +48 -21
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/types.py +2 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/.gitignore +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/LICENSE +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/README.md +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/__init__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/conftest.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/__init__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_missing/__init__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_missing/module.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_with/__init__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_with/outer_1.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_with/outer_2.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_without/__init__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_without/module_1.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/package_without/module_2.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/standalone.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/modules/with_imports.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/scripts/__init__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/scripts/test_async_service/__init__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/scripts/test_async_service/__main__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/scripts/test_async_service/run.sh +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/scripts/test_queue_processor/__init__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/scripts/test_queue_processor/__main__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/scripts/test_queue_processor/run.sh +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_altair.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_astor.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_asyncio.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_atomicwrites.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_atools.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_cachetools.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_click.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_concurrent.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_contextlib.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_contextvars.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_cryptography.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_cvxpy.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_datetime.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_enum.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_errors.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_eventkit.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_fastapi.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_fpdf2.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_functions.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_functools.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_getpass.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_git.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_hashlib.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_http.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_hypothesis.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_ipython.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_iterables.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_jupyter.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_lightweight_charts.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_logging.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_loguru.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_luigi.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_math.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_memory_profiler.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_modules.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_more_itertools.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_numpy.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_operator.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_optuna.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_os.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_pathlib.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_period.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_pickle.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_platform.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_polars.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_polars_ols.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_pqdm.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_pydantic.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_pyinstrument.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_pyrsistent.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_pytest.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_pytest_regressions.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_python_dotenv.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_random.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_re.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_redis.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_reprlib.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_rich.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_scipy.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_sentinel.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_shelve.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_slack_sdk.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_socket.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_sqlalchemy.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_statsmodel.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_streamlit.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_sys.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_tempfile.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_tenacity.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_threading.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_timer.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/__init__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/chain.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/decorated_async.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/decorated_sync.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/error_bind.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/many.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/one.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/recursive.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/task_group_one.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/task_group_two.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/two.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_traceback_funcs/untraced.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_types.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_typing.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_typing_funcs/__init__.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_typing_funcs/no_future.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_tzdata.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_tzlocal.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_uuid.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_version.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_warnings.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_whenever.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_zipfile.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_zoneinfo.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/altair.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/astor.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/asyncio.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/atomicwrites.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/atools.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/cachetools.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/click.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/concurrent.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/contextlib.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/contextvars.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/cryptography.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/cvxpy.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/datetime.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/enum.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/errors.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/eventkit.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/fastapi.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/fpdf2.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/functions.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/functools.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/getpass.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/git.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/hashlib.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/http.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/hypothesis.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/ipython.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/iterables.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/jupyter.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/lightweight_charts.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/logging.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/loguru.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/luigi.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/math.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/memory_profiler.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/modules.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/more_itertools.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/numpy.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/operator.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/optuna.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/orjson.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/os.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/pathlib.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/period.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/pickle.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/platform.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/polars.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/polars_ols.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/pqdm.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/py.typed +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/pydantic.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/pyinstrument.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/pyrsistent.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/pytest.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/pytest_regressions.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/python_dotenv.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/random.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/re.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/redis.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/reprlib.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/rich.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/scipy.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/sentinel.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/shelve.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/slack_sdk.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/socket.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/sqlalchemy.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/statsmodels.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/streamlit.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/sys.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/tempfile.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/tenacity.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/threading.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/timer.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/traceback.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/typing.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/tzdata.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/tzlocal.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/uuid.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/version.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/warnings.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/whenever.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/zipfile.py +0 -0
- {dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/utilities/zoneinfo.py +0 -0
@@ -94,7 +94,7 @@ dependencies = [
|
|
94
94
|
name = "dycw-utilities"
|
95
95
|
readme = "README.md"
|
96
96
|
requires-python = ">= 3.12"
|
97
|
-
version = "0.110.
|
97
|
+
version = "0.110.4"
|
98
98
|
|
99
99
|
[project.optional-dependencies]
|
100
100
|
test = [
|
@@ -337,7 +337,7 @@ zzz-test-zoneinfo = [
|
|
337
337
|
# bump-my-version
|
338
338
|
[tool.bumpversion]
|
339
339
|
allow_dirty = true
|
340
|
-
current_version = "0.110.
|
340
|
+
current_version = "0.110.4"
|
341
341
|
|
342
342
|
[[tool.bumpversion.files]]
|
343
343
|
filename = "src/utilities/__init__.py"
|
@@ -38,6 +38,7 @@ from utilities.dataclasses import (
|
|
38
38
|
OneFieldNonUniqueError,
|
39
39
|
StrMappingToFieldMappingError,
|
40
40
|
YieldFieldsError,
|
41
|
+
_parse_dataclass_split_key_value_pairs,
|
41
42
|
_ParseDataClassParseValueError,
|
42
43
|
_ParseDataClassSplitKeyValuePairsDuplicateKeysError,
|
43
44
|
_ParseDataClassSplitKeyValuePairsSplitError,
|
@@ -364,6 +365,14 @@ class TestOneField:
|
|
364
365
|
)
|
365
366
|
|
366
367
|
|
368
|
+
class TestParseDataClassSplitKeyValuePairs:
|
369
|
+
@given(text=sampled_from(["a=1,b=22,c=333", "{a=1,b=22,c=333}"]))
|
370
|
+
def test_main(self, *, text: str) -> None:
|
371
|
+
result = _parse_dataclass_split_key_value_pairs(text, DataClassFutureInt)
|
372
|
+
expected = {"a": "1", "b": "22", "c": "333"}
|
373
|
+
assert result == expected
|
374
|
+
|
375
|
+
|
367
376
|
class TestReplaceNonSentinel:
|
368
377
|
def test_main(self) -> None:
|
369
378
|
obj = DataClassFutureIntDefault()
|
@@ -382,6 +391,94 @@ class TestReplaceNonSentinel:
|
|
382
391
|
assert obj.int_ == 1
|
383
392
|
|
384
393
|
|
394
|
+
class TestSerializeAndParseDataClass:
|
395
|
+
@given(int_=integers())
|
396
|
+
def test_main_future_int(self, *, int_: int) -> None:
|
397
|
+
obj = DataClassFutureInt(int_=int_)
|
398
|
+
serialized = serialize_dataclass(obj)
|
399
|
+
result = parse_dataclass(serialized, DataClassFutureInt)
|
400
|
+
assert result == obj
|
401
|
+
|
402
|
+
def test_main_future_int_default(self) -> None:
|
403
|
+
obj = DataClassFutureIntDefault()
|
404
|
+
serialized = serialize_dataclass(obj)
|
405
|
+
result = parse_dataclass(serialized, DataClassFutureIntDefault)
|
406
|
+
assert result == obj
|
407
|
+
|
408
|
+
@given(int_=integers())
|
409
|
+
def test_extra_type(self, *, int_: int) -> None:
|
410
|
+
obj = DataClassFutureNestedOuterFirstOuter(
|
411
|
+
inner=DataClassFutureNestedOuterFirstInner(int_=int_)
|
412
|
+
)
|
413
|
+
|
414
|
+
def serializer(obj: DataClassFutureNestedOuterFirstInner, /) -> str:
|
415
|
+
return serialize_dataclass(obj)
|
416
|
+
|
417
|
+
serialized = serialize_dataclass(
|
418
|
+
obj, extra_serializers={DataClassFutureNestedOuterFirstInner: serializer}
|
419
|
+
)
|
420
|
+
result = parse_dataclass(
|
421
|
+
serialized,
|
422
|
+
DataClassFutureNestedOuterFirstOuter,
|
423
|
+
globalns=globals(),
|
424
|
+
extra_parsers={
|
425
|
+
DataClassFutureNestedOuterFirstInner: lambda text: parse_dataclass(
|
426
|
+
text, DataClassFutureNestedOuterFirstInner
|
427
|
+
)
|
428
|
+
},
|
429
|
+
)
|
430
|
+
assert result == obj
|
431
|
+
|
432
|
+
@given(key=sampled_from(["int_", "INT_"]), int_=integers())
|
433
|
+
def test_parse_text_case_insensitive(self, *, key: str, int_: int) -> None:
|
434
|
+
result = parse_dataclass(f"{key}={int_}", DataClassFutureInt)
|
435
|
+
expected = DataClassFutureInt(int_=int_)
|
436
|
+
assert result == expected
|
437
|
+
|
438
|
+
@given(int_=integers())
|
439
|
+
def test_parse_text_case_sensitive(self, *, int_: int) -> None:
|
440
|
+
result = parse_dataclass(
|
441
|
+
f"int_={int_}", DataClassFutureInt, case_sensitive=True
|
442
|
+
)
|
443
|
+
expected = DataClassFutureInt(int_=int_)
|
444
|
+
assert result == expected
|
445
|
+
|
446
|
+
@given(key=sampled_from(["int_", "INT_"]), int_=integers())
|
447
|
+
def test_parse_mapping_case_insensitive(self, *, key: str, int_: int) -> None:
|
448
|
+
result = parse_dataclass({key: str(int_)}, DataClassFutureInt)
|
449
|
+
expected = DataClassFutureInt(int_=int_)
|
450
|
+
assert result == expected
|
451
|
+
|
452
|
+
@given(int_=integers())
|
453
|
+
def test_parse_mapping_case_sensitive(self, *, int_: int) -> None:
|
454
|
+
result = parse_dataclass(
|
455
|
+
{"int_": str(int_)}, DataClassFutureInt, case_sensitive=True
|
456
|
+
)
|
457
|
+
expected = DataClassFutureInt(int_=int_)
|
458
|
+
assert result == expected
|
459
|
+
|
460
|
+
def test_parser_split_key_value_pairs_split(self) -> None:
|
461
|
+
with raises(
|
462
|
+
_ParseDataClassSplitKeyValuePairsSplitError,
|
463
|
+
match="Unable to construct 'DataClassFutureInt'; failed to split key-value pair 'bbb'",
|
464
|
+
):
|
465
|
+
_ = parse_dataclass("a=1,bbb,c=333", DataClassFutureInt)
|
466
|
+
|
467
|
+
def test_error_parse_split_key_value_pairs_duplicate(self) -> None:
|
468
|
+
with raises(
|
469
|
+
_ParseDataClassSplitKeyValuePairsDuplicateKeysError,
|
470
|
+
match=r"Unable to construct 'DataClassFutureInt' since there are duplicate keys; got \{'b': 2\}",
|
471
|
+
):
|
472
|
+
_ = parse_dataclass("a=1,b=22a,b=22b,c=3", DataClassFutureInt)
|
473
|
+
|
474
|
+
def test_error_parse_value(self) -> None:
|
475
|
+
with raises(
|
476
|
+
_ParseDataClassParseValueError,
|
477
|
+
match="Unable to construct 'DataClassFutureInt'; unable to parse field 'int_' of type <class 'int'>; got 'invalid'",
|
478
|
+
):
|
479
|
+
_ = parse_dataclass("int_=invalid", DataClassFutureInt)
|
480
|
+
|
481
|
+
|
385
482
|
class TestStrMappingToFieldMapping:
|
386
483
|
@given(key=sampled_from(["int_", "INT_"]), int_=integers())
|
387
484
|
def test_main_text_case_insensitive(self, *, key: str, int_: int) -> None:
|
@@ -467,70 +564,6 @@ class TestStrMappingToFieldMapping:
|
|
467
564
|
)
|
468
565
|
|
469
566
|
|
470
|
-
class TestSerializeAndParseDataClass:
|
471
|
-
@given(int_=integers())
|
472
|
-
def test_main_future_int(self, *, int_: int) -> None:
|
473
|
-
obj = DataClassFutureInt(int_=int_)
|
474
|
-
serialized = serialize_dataclass(obj)
|
475
|
-
result = parse_dataclass(serialized, DataClassFutureInt)
|
476
|
-
assert result == obj
|
477
|
-
|
478
|
-
def test_main_future_int_default(self) -> None:
|
479
|
-
obj = DataClassFutureIntDefault()
|
480
|
-
serialized = serialize_dataclass(obj)
|
481
|
-
result = parse_dataclass(serialized, DataClassFutureIntDefault)
|
482
|
-
assert result == obj
|
483
|
-
|
484
|
-
@given(key=sampled_from(["int_", "INT_"]), int_=integers())
|
485
|
-
def test_parse_text_case_insensitive(self, *, key: str, int_: int) -> None:
|
486
|
-
result = parse_dataclass(f"{key}={int_}", DataClassFutureInt)
|
487
|
-
expected = DataClassFutureInt(int_=int_)
|
488
|
-
assert result == expected
|
489
|
-
|
490
|
-
@given(int_=integers())
|
491
|
-
def test_parse_text_case_sensitive(self, *, int_: int) -> None:
|
492
|
-
result = parse_dataclass(
|
493
|
-
f"int_={int_}", DataClassFutureInt, case_sensitive=True
|
494
|
-
)
|
495
|
-
expected = DataClassFutureInt(int_=int_)
|
496
|
-
assert result == expected
|
497
|
-
|
498
|
-
@given(key=sampled_from(["int_", "INT_"]), int_=integers())
|
499
|
-
def test_parse_mapping_case_insensitive(self, *, key: str, int_: int) -> None:
|
500
|
-
result = parse_dataclass({key: str(int_)}, DataClassFutureInt)
|
501
|
-
expected = DataClassFutureInt(int_=int_)
|
502
|
-
assert result == expected
|
503
|
-
|
504
|
-
@given(int_=integers())
|
505
|
-
def test_parse_mapping_case_sensitive(self, *, int_: int) -> None:
|
506
|
-
result = parse_dataclass(
|
507
|
-
{"int_": str(int_)}, DataClassFutureInt, case_sensitive=True
|
508
|
-
)
|
509
|
-
expected = DataClassFutureInt(int_=int_)
|
510
|
-
assert result == expected
|
511
|
-
|
512
|
-
def test_parser_split_key_value_pairs_split(self) -> None:
|
513
|
-
with raises(
|
514
|
-
_ParseDataClassSplitKeyValuePairsSplitError,
|
515
|
-
match="Unable to construct 'DataClassFutureInt'; failed to split key-value pair 'bbb'",
|
516
|
-
):
|
517
|
-
_ = parse_dataclass("a=1,bbb,c=333", DataClassFutureInt)
|
518
|
-
|
519
|
-
def test_error_parse_split_key_value_pairs_duplicate(self) -> None:
|
520
|
-
with raises(
|
521
|
-
_ParseDataClassSplitKeyValuePairsDuplicateKeysError,
|
522
|
-
match=r"Unable to construct 'DataClassFutureInt' since there are duplicate keys; got \{'b': 2\}",
|
523
|
-
):
|
524
|
-
_ = parse_dataclass("a=1,b=22a,b=22b,c=3", DataClassFutureInt)
|
525
|
-
|
526
|
-
def test_error_parse_value(self) -> None:
|
527
|
-
with raises(
|
528
|
-
_ParseDataClassParseValueError,
|
529
|
-
match="Unable to construct 'DataClassFutureInt'; unable to parse field 'int_' of type <class 'int'>; got 'invalid'",
|
530
|
-
):
|
531
|
-
_ = parse_dataclass("int_=invalid", DataClassFutureInt)
|
532
|
-
|
533
|
-
|
534
567
|
class TestYieldFields:
|
535
568
|
def test_class_no_future_int(self) -> None:
|
536
569
|
result = one(yield_fields(DataClassNoFutureInt))
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import datetime as dt
|
4
4
|
from collections.abc import Iterable
|
5
|
-
from dataclasses import dataclass
|
6
5
|
from pathlib import Path
|
7
6
|
from types import NoneType
|
8
7
|
from typing import Final, Literal
|
@@ -25,10 +24,13 @@ from pytest import raises
|
|
25
24
|
from tests.test_operator import TruthEnum
|
26
25
|
from tests.test_typing_funcs.with_future import (
|
27
26
|
DataClassFutureInt,
|
27
|
+
DataClassFutureIntChild,
|
28
28
|
DataClassFutureIntEven,
|
29
29
|
DataClassFutureIntEvenOrOddTypeUnion,
|
30
30
|
DataClassFutureIntEvenOrOddUnion,
|
31
31
|
DataClassFutureIntOdd,
|
32
|
+
DataClassFutureIntParentFirst,
|
33
|
+
DataClassFutureIntParentSecond,
|
32
34
|
TrueOrFalseFutureLit,
|
33
35
|
TrueOrFalseFutureTypeLit,
|
34
36
|
)
|
@@ -48,6 +50,8 @@ from utilities.math import is_equal
|
|
48
50
|
from utilities.parse import (
|
49
51
|
_ParseObjectExtraNonUniqueError,
|
50
52
|
_ParseObjectParseError,
|
53
|
+
_SerializeObjectExtraNonUniqueError,
|
54
|
+
_SerializeObjectSerializeError,
|
51
55
|
parse_object,
|
52
56
|
serialize_object,
|
53
57
|
)
|
@@ -99,11 +103,7 @@ class TestSerializeAndParseObject:
|
|
99
103
|
result = parse_object(
|
100
104
|
DataClassFutureInt,
|
101
105
|
serialized,
|
102
|
-
extra={
|
103
|
-
DataClassFutureInt: lambda serialized: DataClassFutureInt(
|
104
|
-
int_=int(serialized)
|
105
|
-
)
|
106
|
-
},
|
106
|
+
extra={DataClassFutureInt: lambda text: DataClassFutureInt(int_=int(text))},
|
107
107
|
)
|
108
108
|
expected = DataClassFutureInt(int_=value)
|
109
109
|
assert result == expected
|
@@ -240,7 +240,7 @@ class TestSerializeAndParseObject:
|
|
240
240
|
|
241
241
|
@given(value=integers())
|
242
242
|
def test_type_union_with_extra(self, *, value: int) -> None:
|
243
|
-
def
|
243
|
+
def parser(text: str, /) -> DataClassFutureIntEvenOrOddTypeUnion:
|
244
244
|
value = int(text)
|
245
245
|
match value % 2:
|
246
246
|
case 0:
|
@@ -254,7 +254,7 @@ class TestSerializeAndParseObject:
|
|
254
254
|
result = parse_object(
|
255
255
|
DataClassFutureIntEvenOrOddTypeUnion,
|
256
256
|
serialized,
|
257
|
-
extra={DataClassFutureIntEvenOrOddTypeUnion:
|
257
|
+
extra={DataClassFutureIntEvenOrOddTypeUnion: parser},
|
258
258
|
)
|
259
259
|
match value % 2:
|
260
260
|
case 0:
|
@@ -267,7 +267,7 @@ class TestSerializeAndParseObject:
|
|
267
267
|
|
268
268
|
@given(value=integers())
|
269
269
|
def test_union_with_extra(self, *, value: int) -> None:
|
270
|
-
def
|
270
|
+
def parser(text: str, /) -> DataClassFutureIntEvenOrOddUnion:
|
271
271
|
value = int(text)
|
272
272
|
match value % 2:
|
273
273
|
case 0:
|
@@ -281,7 +281,7 @@ class TestSerializeAndParseObject:
|
|
281
281
|
result = parse_object(
|
282
282
|
DataClassFutureIntEvenOrOddUnion,
|
283
283
|
serialized,
|
284
|
-
extra={DataClassFutureIntEvenOrOddUnion:
|
284
|
+
extra={DataClassFutureIntEvenOrOddUnion: parser},
|
285
285
|
)
|
286
286
|
match value % 2:
|
287
287
|
case 0:
|
@@ -299,7 +299,7 @@ class TestSerializeAndParseObject:
|
|
299
299
|
assert result == version
|
300
300
|
|
301
301
|
|
302
|
-
class
|
302
|
+
class TestParseObject:
|
303
303
|
def test_error_bool(self) -> None:
|
304
304
|
with raises(
|
305
305
|
_ParseObjectParseError,
|
@@ -357,27 +357,20 @@ class TestParseSerialized:
|
|
357
357
|
|
358
358
|
@given(value=integers())
|
359
359
|
def test_error_extra_non_unique(self, *, value: int) -> None:
|
360
|
-
@dataclass(kw_only=True)
|
361
|
-
class Parent1:
|
362
|
-
x: int = 0
|
363
|
-
|
364
|
-
@dataclass(kw_only=True)
|
365
|
-
class Parent2:
|
366
|
-
y: int = 0
|
367
|
-
|
368
|
-
@dataclass(kw_only=True)
|
369
|
-
class Child(Parent1, Parent2): ...
|
370
|
-
|
371
360
|
with raises(
|
372
361
|
_ParseObjectExtraNonUniqueError,
|
373
362
|
match="Unable to parse <class '.*'> since `extra` must contain exactly one parent class; got <function .*>, <function .*> and perhaps more",
|
374
363
|
):
|
375
364
|
_ = parse_object(
|
376
|
-
|
365
|
+
DataClassFutureIntChild,
|
377
366
|
serialize_object(value),
|
378
367
|
extra={
|
379
|
-
|
380
|
-
|
368
|
+
DataClassFutureIntParentFirst: lambda text: DataClassFutureIntChild(
|
369
|
+
int1=int(text), int2=0
|
370
|
+
),
|
371
|
+
DataClassFutureIntParentSecond: lambda text: DataClassFutureIntChild(
|
372
|
+
int1=0, int2=int(text)
|
373
|
+
),
|
381
374
|
},
|
382
375
|
)
|
383
376
|
|
@@ -538,6 +531,33 @@ class TestParseSerialized:
|
|
538
531
|
|
539
532
|
|
540
533
|
class TestSerializeObject:
|
534
|
+
def test_error_extra_empty(self) -> None:
|
535
|
+
with raises(
|
536
|
+
_SerializeObjectSerializeError,
|
537
|
+
match=r"Unable to serialize object typing\.Final",
|
538
|
+
):
|
539
|
+
_ = serialize_object(Final, extra={})
|
540
|
+
|
541
|
+
@given(int1=integers(), int2=integers())
|
542
|
+
def test_error_extra_non_unique(self, *, int1: int, int2: int) -> None:
|
543
|
+
def serializer1(obj: DataClassFutureIntParentFirst, /) -> str:
|
544
|
+
return str(obj.int1)
|
545
|
+
|
546
|
+
def serializer2(obj: DataClassFutureIntParentSecond, /) -> str:
|
547
|
+
return str(obj.int2)
|
548
|
+
|
549
|
+
with raises(
|
550
|
+
_SerializeObjectExtraNonUniqueError,
|
551
|
+
match=r"Unable to serialize object DataClassFutureIntChild\(.*\) since `extra` must contain exactly one parent class; got <function .*>, <function .*> and perhaps more",
|
552
|
+
):
|
553
|
+
_ = serialize_object(
|
554
|
+
DataClassFutureIntChild(int1=int1, int2=int2),
|
555
|
+
extra={
|
556
|
+
DataClassFutureIntParentFirst: serializer1,
|
557
|
+
DataClassFutureIntParentSecond: serializer2,
|
558
|
+
},
|
559
|
+
)
|
560
|
+
|
541
561
|
def test_error_not_implemented(self) -> None:
|
542
|
-
with raises(
|
562
|
+
with raises(_SerializeObjectSerializeError):
|
543
563
|
_ = serialize_object(Final)
|
@@ -90,6 +90,8 @@ class TestSplitKeyValuePairs:
|
|
90
90
|
("a=", [("a", "")]),
|
91
91
|
("a=1,=22,c=333", [("a", "1"), ("", "22"), ("c", "333")]),
|
92
92
|
("a=1,b=,c=333", [("a", "1"), ("b", ""), ("c", "333")]),
|
93
|
+
("a=1,b=(22,22,22),c=333", [("a", "1"), ("b", "(22,22,22)"), ("c", "333")]),
|
94
|
+
("a=1,b=(c=22),c=333", [("a", "1"), ("b", "(c=22)"), ("c", "333")]),
|
93
95
|
])
|
94
96
|
)
|
95
97
|
def test_main(self, *, case: tuple[str, Sequence[tuple[str, str]]]) -> None:
|
@@ -102,10 +104,17 @@ class TestSplitKeyValuePairs:
|
|
102
104
|
expected = {"a": "1", "b": "22", "c": "333"}
|
103
105
|
assert result == expected
|
104
106
|
|
105
|
-
def
|
107
|
+
def test_error_split_list(self) -> None:
|
106
108
|
with raises(
|
107
109
|
_SplitKeyValuePairsSplitError,
|
108
|
-
match=r"Unable to split 'a=1,b=22
|
110
|
+
match=r"Unable to split 'a=1,b=\(c=22\],d=333' into key-value pairs",
|
111
|
+
):
|
112
|
+
_ = split_key_value_pairs("a=1,b=(c=22],d=333")
|
113
|
+
|
114
|
+
def test_error_split_pair(self) -> None:
|
115
|
+
with raises(
|
116
|
+
_SplitKeyValuePairsSplitError,
|
117
|
+
match=r"Unable to split 'a=1,b=22=22,c=333' into key-value pairs",
|
109
118
|
):
|
110
119
|
_ = split_key_value_pairs("a=1,b=22=22,c=333")
|
111
120
|
|
{dycw_utilities-0.110.2 → dycw_utilities-0.110.4}/src/tests/test_typing_funcs/with_future.py
RENAMED
@@ -87,6 +87,22 @@ class DataClassFutureIntOneAndTwo:
|
|
87
87
|
int2: int
|
88
88
|
|
89
89
|
|
90
|
+
@dataclass(order=True, unsafe_hash=True, kw_only=True)
|
91
|
+
class DataClassFutureIntParentFirst:
|
92
|
+
int1: int
|
93
|
+
|
94
|
+
|
95
|
+
@dataclass(order=True, unsafe_hash=True, kw_only=True)
|
96
|
+
class DataClassFutureIntParentSecond:
|
97
|
+
int2: int
|
98
|
+
|
99
|
+
|
100
|
+
@dataclass(order=True, unsafe_hash=True, kw_only=True)
|
101
|
+
class DataClassFutureIntChild(
|
102
|
+
DataClassFutureIntParentFirst, DataClassFutureIntParentSecond
|
103
|
+
): ...
|
104
|
+
|
105
|
+
|
90
106
|
@dataclass(order=True, unsafe_hash=True, kw_only=True)
|
91
107
|
class DataClassFutureListInts:
|
92
108
|
ints: list[int]
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from collections.abc import Mapping
|
4
|
+
from contextlib import suppress
|
4
5
|
from dataclasses import MISSING, dataclass, field, fields, replace
|
5
6
|
from typing import (
|
6
7
|
TYPE_CHECKING,
|
@@ -21,21 +22,23 @@ from utilities.functions import (
|
|
21
22
|
)
|
22
23
|
from utilities.iterables import OneStrEmptyError, OneStrNonUniqueError, one_str
|
23
24
|
from utilities.operator import is_equal
|
24
|
-
from utilities.parse import
|
25
|
-
|
26
|
-
PAIR_SEPARATOR,
|
27
|
-
ParseObjectError,
|
28
|
-
parse_object,
|
29
|
-
serialize_object,
|
30
|
-
)
|
25
|
+
from utilities.parse import ParseObjectError, parse_object, serialize_object
|
26
|
+
from utilities.re import ExtractGroupError, extract_group
|
31
27
|
from utilities.sentinel import Sentinel, sentinel
|
32
28
|
from utilities.text import (
|
29
|
+
BRACKETS,
|
30
|
+
LIST_SEPARATOR,
|
31
|
+
PAIR_SEPARATOR,
|
33
32
|
_SplitKeyValuePairsDuplicateKeysError,
|
34
33
|
_SplitKeyValuePairsSplitError,
|
35
|
-
join_strs,
|
36
34
|
split_key_value_pairs,
|
37
35
|
)
|
38
|
-
from utilities.types import
|
36
|
+
from utilities.types import (
|
37
|
+
ParseObjectExtra,
|
38
|
+
SerializeObjectExtra,
|
39
|
+
StrStrMapping,
|
40
|
+
TDataclass,
|
41
|
+
)
|
39
42
|
from utilities.typing import get_type_hints
|
40
43
|
|
41
44
|
if TYPE_CHECKING:
|
@@ -408,10 +411,11 @@ def serialize_dataclass(
|
|
408
411
|
exclude: Iterable[str] | None = None,
|
409
412
|
rel_tol: float | None = None,
|
410
413
|
abs_tol: float | None = None,
|
411
|
-
|
414
|
+
extra_equal: Mapping[type[_U], Callable[[_U, _U], bool]] | None = None,
|
412
415
|
defaults: bool = False,
|
413
416
|
list_separator: str = LIST_SEPARATOR,
|
414
417
|
pair_separator: str = PAIR_SEPARATOR,
|
418
|
+
extra_serializers: SerializeObjectExtra | None = None,
|
415
419
|
) -> str:
|
416
420
|
"""Serialize a Dataclass."""
|
417
421
|
mapping: StrStrMapping = {}
|
@@ -426,16 +430,21 @@ def serialize_dataclass(
|
|
426
430
|
exclude=exclude,
|
427
431
|
rel_tol=rel_tol,
|
428
432
|
abs_tol=abs_tol,
|
429
|
-
extra=
|
433
|
+
extra=extra_equal,
|
430
434
|
defaults=defaults,
|
431
435
|
):
|
432
436
|
mapping[fld.name] = serialize_object(
|
433
|
-
fld.value,
|
437
|
+
fld.value,
|
438
|
+
list_separator=list_separator,
|
439
|
+
pair_separator=pair_separator,
|
440
|
+
extra=extra_serializers,
|
434
441
|
)
|
435
|
-
|
436
|
-
|
442
|
+
return serialize_object(
|
443
|
+
mapping,
|
444
|
+
list_separator=list_separator,
|
445
|
+
pair_separator=pair_separator,
|
446
|
+
extra=extra_serializers,
|
437
447
|
)
|
438
|
-
return join_strs(joined_items, separator=list_separator)
|
439
448
|
|
440
449
|
|
441
450
|
def parse_dataclass(
|
@@ -445,6 +454,7 @@ def parse_dataclass(
|
|
445
454
|
*,
|
446
455
|
list_separator: str = LIST_SEPARATOR,
|
447
456
|
pair_separator: str = PAIR_SEPARATOR,
|
457
|
+
brackets: Iterable[tuple[str, str]] | None = BRACKETS,
|
448
458
|
globalns: StrMapping | None = None,
|
449
459
|
localns: StrMapping | None = None,
|
450
460
|
warn_name_errors: bool = False,
|
@@ -457,7 +467,11 @@ def parse_dataclass(
|
|
457
467
|
match text_or_mapping:
|
458
468
|
case str() as text:
|
459
469
|
keys_to_serializes = _parse_dataclass_split_key_value_pairs(
|
460
|
-
text,
|
470
|
+
text,
|
471
|
+
cls,
|
472
|
+
list_separator=list_separator,
|
473
|
+
pair_separator=pair_separator,
|
474
|
+
brackets=brackets,
|
461
475
|
)
|
462
476
|
case Mapping() as keys_to_serializes:
|
463
477
|
...
|
@@ -481,7 +495,14 @@ def parse_dataclass(
|
|
481
495
|
)
|
482
496
|
field_names_to_values = {
|
483
497
|
f.name: _parse_dataclass_parse_text(
|
484
|
-
f,
|
498
|
+
f,
|
499
|
+
t,
|
500
|
+
cls,
|
501
|
+
list_separator=list_separator,
|
502
|
+
pair_separator=pair_separator,
|
503
|
+
head=head,
|
504
|
+
case_sensitive=case_sensitive,
|
505
|
+
extra=extra_parsers,
|
485
506
|
)
|
486
507
|
for f, t in fields_to_serializes.items()
|
487
508
|
}
|
@@ -505,12 +526,16 @@ def _parse_dataclass_split_key_value_pairs(
|
|
505
526
|
*,
|
506
527
|
list_separator: str = LIST_SEPARATOR,
|
507
528
|
pair_separator: str = PAIR_SEPARATOR,
|
529
|
+
brackets: Iterable[tuple[str, str]] | None = BRACKETS,
|
508
530
|
) -> StrStrMapping:
|
531
|
+
with suppress(ExtractGroupError):
|
532
|
+
text = extract_group(r"^\{?(.*?)\}?$", text)
|
509
533
|
try:
|
510
534
|
return split_key_value_pairs(
|
511
535
|
text,
|
512
536
|
list_separator=list_separator,
|
513
537
|
pair_separator=pair_separator,
|
538
|
+
brackets=brackets,
|
514
539
|
mapping=True,
|
515
540
|
)
|
516
541
|
except _SplitKeyValuePairsSplitError as error:
|