dycw-utilities 0.108.3__tar.gz → 0.108.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.108.3 → dycw_utilities-0.108.4}/PKG-INFO +5 -5
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/pyproject.toml +8 -8
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_dataclasses.py +82 -20
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/__init__.py +1 -1
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/dataclasses.py +166 -18
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/.gitignore +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/LICENSE +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/README.md +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/__init__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/conftest.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/__init__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_missing/__init__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_missing/module.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_with/__init__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_with/outer_1.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_with/outer_2.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_without/__init__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_without/module_1.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_without/module_2.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/standalone.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/with_imports.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/__init__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_async_service/__init__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_async_service/__main__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_async_service/run.sh +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_queue_processor/__init__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_queue_processor/__main__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_queue_processor/run.sh +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_altair.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_astor.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_asyncio.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_atomicwrites.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_atools.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_cachetools.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_click.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_concurrent.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_contextlib.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_contextvars.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_cryptography.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_cvxpy.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_datetime.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_enum.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_errors.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_eventkit.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_fastapi.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_fpdf2.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_functions.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_functools.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_getpass.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_git.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_hashlib.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_http.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_hypothesis.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_ipython.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_iterables.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_jupyter.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_logging.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_loguru.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_luigi.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_math.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_memory_profiler.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_modules.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_more_itertools.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_numpy.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_operator.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_optuna.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_orjson.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_os.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_parse.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_pathlib.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_period.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_pickle.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_platform.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_polars.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_pqdm.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_pydantic.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_pyinstrument.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_pyrsistent.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_pytest.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_pytest_regressions.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_python_dotenv.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_random.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_re.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_redis.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_reprlib.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_rich.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_scipy.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_sentinel.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_shelve.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_slack_sdk.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_socket.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_sqlalchemy.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_streamlit.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_sys.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_tempfile.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_tenacity.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_text.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_threading.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_timer.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/__init__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/chain.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/decorated_async.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/decorated_sync.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/error_bind.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/many.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/one.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/recursive.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/task_group_one.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/task_group_two.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/two.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_traceback_funcs/untraced.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_types.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_typing.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_typing_funcs/__init__.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_typing_funcs/no_future.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_typing_funcs/with_future.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_tzdata.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_tzlocal.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_uuid.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_version.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_warnings.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_whenever.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_zipfile.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/test_zoneinfo.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/altair.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/astor.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/asyncio.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/atomicwrites.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/atools.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/cachetools.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/click.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/concurrent.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/contextlib.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/contextvars.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/cryptography.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/cvxpy.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/datetime.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/enum.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/errors.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/eventkit.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/fastapi.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/fpdf2.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/functions.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/functools.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/getpass.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/git.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/hashlib.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/http.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/hypothesis.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/ipython.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/iterables.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/jupyter.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/logging.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/loguru.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/luigi.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/math.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/memory_profiler.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/modules.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/more_itertools.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/numpy.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/operator.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/optuna.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/orjson.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/os.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/parse.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/pathlib.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/period.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/pickle.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/platform.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/polars.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/pqdm.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/py.typed +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/pydantic.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/pyinstrument.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/pyrsistent.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/pytest.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/pytest_regressions.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/python_dotenv.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/random.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/re.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/redis.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/reprlib.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/rich.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/scipy.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/sentinel.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/shelve.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/slack_sdk.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/socket.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/sqlalchemy.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/streamlit.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/sys.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/tempfile.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/tenacity.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/text.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/threading.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/timer.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/traceback.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/types.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/typing.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/tzdata.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/tzlocal.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/uuid.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/version.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/warnings.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/whenever.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/zipfile.py +0 -0
- {dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/utilities/zoneinfo.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dycw-utilities
|
3
|
-
Version: 0.108.
|
3
|
+
Version: 0.108.4
|
4
4
|
Author-email: Derek Wan <d.wan@icloud.com>
|
5
5
|
License-File: LICENSE
|
6
6
|
Requires-Python: >=3.12
|
@@ -82,7 +82,7 @@ Requires-Dist: asyncpg<0.31,>=0.30.0; extra == 'zzz-test-hypothesis'
|
|
82
82
|
Requires-Dist: greenlet<3.3,>=3.2.0; extra == 'zzz-test-hypothesis'
|
83
83
|
Requires-Dist: hypothesis<6.132,>=6.131.6; extra == 'zzz-test-hypothesis'
|
84
84
|
Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-hypothesis'
|
85
|
-
Requires-Dist: numpy<2.3,>=2.2.
|
85
|
+
Requires-Dist: numpy<2.3,>=2.2.5; extra == 'zzz-test-hypothesis'
|
86
86
|
Requires-Dist: pathvalidate<3.3,>=3.2.3; extra == 'zzz-test-hypothesis'
|
87
87
|
Requires-Dist: redis<5.3,>=5.2.1; extra == 'zzz-test-hypothesis'
|
88
88
|
Requires-Dist: sqlalchemy<2.1,>=2.0.40; extra == 'zzz-test-hypothesis'
|
@@ -112,14 +112,14 @@ Provides-Extra: zzz-test-luigi
|
|
112
112
|
Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-luigi'
|
113
113
|
Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-luigi'
|
114
114
|
Provides-Extra: zzz-test-math
|
115
|
-
Requires-Dist: numpy<2.3,>=2.2.
|
115
|
+
Requires-Dist: numpy<2.3,>=2.2.5; extra == 'zzz-test-math'
|
116
116
|
Provides-Extra: zzz-test-memory-profiler
|
117
117
|
Requires-Dist: memory-profiler<0.62,>=0.61.0; extra == 'zzz-test-memory-profiler'
|
118
118
|
Provides-Extra: zzz-test-modules
|
119
119
|
Provides-Extra: zzz-test-more-itertools
|
120
120
|
Requires-Dist: more-itertools<10.7,>=10.6.0; extra == 'zzz-test-more-itertools'
|
121
121
|
Provides-Extra: zzz-test-numpy
|
122
|
-
Requires-Dist: numpy<2.3,>=2.2.
|
122
|
+
Requires-Dist: numpy<2.3,>=2.2.5; extra == 'zzz-test-numpy'
|
123
123
|
Provides-Extra: zzz-test-operator
|
124
124
|
Requires-Dist: polars-lts-cpu<1.28,>=1.27.1; extra == 'zzz-test-operator'
|
125
125
|
Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-operator'
|
@@ -177,7 +177,7 @@ Requires-Dist: scipy<1.16,>=1.15.2; extra == 'zzz-test-scipy'
|
|
177
177
|
Provides-Extra: zzz-test-sentinel
|
178
178
|
Provides-Extra: zzz-test-shelve
|
179
179
|
Provides-Extra: zzz-test-slack-sdk
|
180
|
-
Requires-Dist: aiohttp<3.12,>=3.11.
|
180
|
+
Requires-Dist: aiohttp<3.12,>=3.11.17; extra == 'zzz-test-slack-sdk'
|
181
181
|
Requires-Dist: slack-sdk<3.36,>=3.35.0; extra == 'zzz-test-slack-sdk'
|
182
182
|
Provides-Extra: zzz-test-socket
|
183
183
|
Provides-Extra: zzz-test-sqlalchemy
|
@@ -8,7 +8,7 @@ requires = ["hatchling"]
|
|
8
8
|
# dependency groups
|
9
9
|
[dependency-groups]
|
10
10
|
dev = [
|
11
|
-
"aiohttp >= 3.11.
|
11
|
+
"aiohttp >= 3.11.17, < 3.12", # for slack
|
12
12
|
"aiosqlite >= 0.21.0, < 0.22",
|
13
13
|
"altair >= 5.5.0, < 5.6",
|
14
14
|
"astor >= 0.8.1, < 0.9",
|
@@ -35,7 +35,7 @@ dev = [
|
|
35
35
|
"more-itertools >= 10.6.0, < 10.7",
|
36
36
|
"nest-asyncio >= 1.6.0, < 1.7", # for sqlalchemy async
|
37
37
|
"nox >= 2025.2.9, < 2025.3",
|
38
|
-
"numpy >= 2.2.
|
38
|
+
"numpy >= 2.2.5, < 2.3",
|
39
39
|
"optuna >= 4.3.0, < 4.4",
|
40
40
|
"orjson >= 3.10.16, < 3.11",
|
41
41
|
"pathvalidate >= 3.2.3, < 3.3",
|
@@ -89,7 +89,7 @@ dependencies = [
|
|
89
89
|
name = "dycw-utilities"
|
90
90
|
readme = "README.md"
|
91
91
|
requires-python = ">= 3.12"
|
92
|
-
version = "0.108.
|
92
|
+
version = "0.108.4"
|
93
93
|
|
94
94
|
[project.optional-dependencies]
|
95
95
|
test = [
|
@@ -173,7 +173,7 @@ zzz-test-hypothesis = [
|
|
173
173
|
"greenlet >= 3.2.0, < 3.3", # for sqlalchemy async
|
174
174
|
"hypothesis >= 6.131.6, < 6.132",
|
175
175
|
"luigi >= 3.6.0, < 3.7",
|
176
|
-
"numpy >= 2.2.
|
176
|
+
"numpy >= 2.2.5, < 2.3",
|
177
177
|
"pathvalidate >= 3.2.3, < 3.3",
|
178
178
|
"redis >= 5.2.1, < 5.3",
|
179
179
|
"sqlalchemy >= 2.0.40, < 2.1",
|
@@ -205,11 +205,11 @@ zzz-test-luigi = [
|
|
205
205
|
"luigi >= 3.6.0, < 3.7",
|
206
206
|
"whenever >= 0.7.3, < 0.8",
|
207
207
|
]
|
208
|
-
zzz-test-math = ["numpy >= 2.2.
|
208
|
+
zzz-test-math = ["numpy >= 2.2.5, < 2.3"]
|
209
209
|
zzz-test-memory-profiler = ["memory-profiler >= 0.61.0, < 0.62"]
|
210
210
|
zzz-test-modules = []
|
211
211
|
zzz-test-more-itertools = ["more-itertools >= 10.6.0, < 10.7"]
|
212
|
-
zzz-test-numpy = ["numpy >= 2.2.
|
212
|
+
zzz-test-numpy = ["numpy >= 2.2.5, < 2.3"]
|
213
213
|
zzz-test-operator = [
|
214
214
|
"polars-lts-cpu >= 1.27.1, < 1.28",
|
215
215
|
"whenever >= 0.7.3, < 0.8",
|
@@ -268,7 +268,7 @@ zzz-test-scipy = ["scipy >= 1.15.2, < 1.16"]
|
|
268
268
|
zzz-test-sentinel = []
|
269
269
|
zzz-test-shelve = []
|
270
270
|
zzz-test-slack-sdk = [
|
271
|
-
"aiohttp >= 3.11.
|
271
|
+
"aiohttp >= 3.11.17, < 3.12", # for slack
|
272
272
|
"slack-sdk >= 3.35.0, < 3.36",
|
273
273
|
]
|
274
274
|
zzz-test-socket = []
|
@@ -332,7 +332,7 @@ zzz-test-zoneinfo = [
|
|
332
332
|
# bump-my-version
|
333
333
|
[tool.bumpversion]
|
334
334
|
allow_dirty = true
|
335
|
-
current_version = "0.108.
|
335
|
+
current_version = "0.108.4"
|
336
336
|
|
337
337
|
[[tool.bumpversion.files]]
|
338
338
|
filename = "src/utilities/__init__.py"
|
@@ -45,12 +45,17 @@ from utilities.dataclasses import (
|
|
45
45
|
YieldFieldsError,
|
46
46
|
_MappingToDataclassCaseInsensitiveNonUniqueError,
|
47
47
|
_MappingToDataclassEmptyError,
|
48
|
+
_TextToDataClassGetFieldEmptyError,
|
49
|
+
_TextToDataClassGetFieldNonUniqueError,
|
50
|
+
_TextToDataClassParseValueError,
|
51
|
+
_TextToDataClassSplitKeyValuePairError,
|
48
52
|
_YieldFieldsClass,
|
49
53
|
_YieldFieldsInstance,
|
50
54
|
dataclass_repr,
|
51
55
|
dataclass_to_dict,
|
52
56
|
mapping_to_dataclass,
|
53
57
|
replace_non_sentinel,
|
58
|
+
text_to_dataclass,
|
54
59
|
yield_fields,
|
55
60
|
)
|
56
61
|
from utilities.functions import get_class_name
|
@@ -65,6 +70,43 @@ from utilities.typing import get_args, is_list_type, is_literal_type, is_optiona
|
|
65
70
|
TruthLit = Literal["true", "false"] # in 3.12, use type TruthLit = ...
|
66
71
|
|
67
72
|
|
73
|
+
class TestDataClassRepr:
|
74
|
+
def test_overriding_repr(self) -> None:
|
75
|
+
@dataclass(kw_only=True, slots=True)
|
76
|
+
class Example(DataClassFutureIntDefault):
|
77
|
+
@override
|
78
|
+
def __repr__(self) -> str:
|
79
|
+
return dataclass_repr(self)
|
80
|
+
|
81
|
+
obj = Example()
|
82
|
+
result = repr(obj)
|
83
|
+
expected = "Example()"
|
84
|
+
assert result == expected
|
85
|
+
|
86
|
+
def test_overriding_repr_defaults(self) -> None:
|
87
|
+
@dataclass(kw_only=True)
|
88
|
+
class Example(DataClassFutureIntDefault):
|
89
|
+
@override
|
90
|
+
def __repr__(self) -> str:
|
91
|
+
return dataclass_repr(self, defaults=True)
|
92
|
+
|
93
|
+
obj = Example()
|
94
|
+
result = repr(obj)
|
95
|
+
expected = "Example(int_=0)"
|
96
|
+
assert result == expected
|
97
|
+
|
98
|
+
@given(x=integers())
|
99
|
+
def test_non_repr_field(self, *, x: int) -> None:
|
100
|
+
@dataclass(kw_only=True, slots=True)
|
101
|
+
class Example:
|
102
|
+
x: int = field(default=0, repr=False)
|
103
|
+
|
104
|
+
obj = Example(x=x)
|
105
|
+
result = dataclass_repr(obj)
|
106
|
+
expected = "Example()"
|
107
|
+
assert result == expected
|
108
|
+
|
109
|
+
|
68
110
|
class TestDataclassToDictAndDataclassRepr:
|
69
111
|
@given(x=integers(), defaults=booleans())
|
70
112
|
def test_field_without_defaults(self, *, x: int, defaults: bool) -> None:
|
@@ -328,31 +370,51 @@ class TestReplaceNonSentinel:
|
|
328
370
|
assert obj.int_ == 1
|
329
371
|
|
330
372
|
|
331
|
-
class
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
@override
|
338
|
-
def __repr__(self) -> str:
|
339
|
-
return dataclass_repr(self)
|
373
|
+
class TestTextToDataClass:
|
374
|
+
@given(int_=integers())
|
375
|
+
def test_main_text(self, *, int_: int) -> None:
|
376
|
+
result = text_to_dataclass(f"int_={int_}", DataClassFutureInt)
|
377
|
+
expected = DataClassFutureInt(int_=int_)
|
378
|
+
assert result == expected
|
340
379
|
|
341
|
-
|
342
|
-
|
343
|
-
|
380
|
+
@given(int_=integers())
|
381
|
+
def test_main_mapping(self, *, int_: int) -> None:
|
382
|
+
result = text_to_dataclass({"int_": str(int_)}, DataClassFutureInt)
|
383
|
+
expected = DataClassFutureInt(int_=int_)
|
344
384
|
assert result == expected
|
345
385
|
|
346
|
-
|
347
|
-
|
348
|
-
|
386
|
+
def test_error_split_key_value_pair(self) -> None:
|
387
|
+
with raises(
|
388
|
+
_TextToDataClassSplitKeyValuePairError,
|
389
|
+
match="Unable to construct 'DataClassFutureInt'; failed to split key-value pair 'keyvalue'",
|
390
|
+
):
|
391
|
+
_ = text_to_dataclass("keyvalue", DataClassFutureInt)
|
392
|
+
|
393
|
+
def test_error_get_field_empty(self) -> None:
|
394
|
+
with raises(
|
395
|
+
_TextToDataClassGetFieldEmptyError,
|
396
|
+
match=r"Dataclass 'DataClassFutureInt' does not contain any field starting with 'k' \(modulo case\)",
|
397
|
+
):
|
398
|
+
_ = text_to_dataclass("k=value", DataClassFutureInt)
|
399
|
+
|
400
|
+
def test_error_get_field_non_unique(self) -> None:
|
401
|
+
@dataclass(order=True, unsafe_hash=True, kw_only=True)
|
349
402
|
class Example:
|
350
|
-
|
403
|
+
int1: int
|
404
|
+
int2: int
|
351
405
|
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
406
|
+
with raises(
|
407
|
+
_TextToDataClassGetFieldNonUniqueError,
|
408
|
+
match=r"Dataclass 'Example' must contain exactly one field starting with 'int' \(modulo case\); got 'int1', 'int2' and perhaps more",
|
409
|
+
):
|
410
|
+
_ = text_to_dataclass("int=value", Example)
|
411
|
+
|
412
|
+
def test_error_parse_value(self) -> None:
|
413
|
+
with raises(
|
414
|
+
_TextToDataClassParseValueError,
|
415
|
+
match="Unable to construct 'DataClassFutureInt'; unable to parse field 'int_' of type <class 'int'>; got 'invalid'",
|
416
|
+
):
|
417
|
+
_ = text_to_dataclass("int_=invalid", DataClassFutureInt)
|
356
418
|
|
357
419
|
|
358
420
|
class TestYieldFields:
|
@@ -1,7 +1,17 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
from collections.abc import Mapping
|
3
4
|
from dataclasses import MISSING, dataclass, field, fields, replace
|
4
|
-
from typing import
|
5
|
+
from typing import (
|
6
|
+
TYPE_CHECKING,
|
7
|
+
Any,
|
8
|
+
Generic,
|
9
|
+
Literal,
|
10
|
+
TypeVar,
|
11
|
+
assert_never,
|
12
|
+
overload,
|
13
|
+
override,
|
14
|
+
)
|
5
15
|
|
6
16
|
from utilities.errors import ImpossibleCaseError
|
7
17
|
from utilities.functions import (
|
@@ -11,14 +21,16 @@ from utilities.functions import (
|
|
11
21
|
)
|
12
22
|
from utilities.iterables import OneStrEmptyError, OneStrNonUniqueError, one_str
|
13
23
|
from utilities.operator import is_equal
|
24
|
+
from utilities.parse import ParseTextError, parse_text
|
14
25
|
from utilities.reprlib import get_repr
|
15
26
|
from utilities.sentinel import Sentinel, sentinel
|
27
|
+
from utilities.types import TDataclass
|
16
28
|
from utilities.typing import get_type_hints
|
17
29
|
|
18
30
|
if TYPE_CHECKING:
|
19
|
-
from collections.abc import Callable, Iterable, Iterator
|
31
|
+
from collections.abc import Callable, Iterable, Iterator
|
20
32
|
|
21
|
-
from utilities.types import Dataclass, StrMapping
|
33
|
+
from utilities.types import Dataclass, StrMapping
|
22
34
|
|
23
35
|
|
24
36
|
_T = TypeVar("_T")
|
@@ -118,7 +130,7 @@ def dataclass_to_dict(
|
|
118
130
|
recursive: bool = False,
|
119
131
|
) -> StrMapping:
|
120
132
|
"""Convert a dataclass to a dictionary."""
|
121
|
-
out:
|
133
|
+
out: StrMapping = {}
|
122
134
|
for fld in yield_fields(obj, globalns=globalns, localns=localns):
|
123
135
|
if fld.keep(
|
124
136
|
include=include,
|
@@ -233,9 +245,7 @@ class _MappingToDataclassEmptyError(MappingToDataclassError):
|
|
233
245
|
@override
|
234
246
|
def __str__(self) -> str:
|
235
247
|
desc = f"Mapping {get_repr(self.mapping)} does not contain {self.field!r}"
|
236
|
-
if
|
237
|
-
desc += " (modulo case)"
|
238
|
-
return desc
|
248
|
+
return desc if self.case_sensitive else f"{desc} (modulo case)"
|
239
249
|
|
240
250
|
|
241
251
|
@dataclass(kw_only=True, slots=True)
|
@@ -280,6 +290,142 @@ def replace_non_sentinel(
|
|
280
290
|
##
|
281
291
|
|
282
292
|
|
293
|
+
def text_to_dataclass(
|
294
|
+
text_or_mapping: str | Mapping[str, str],
|
295
|
+
cls: type[TDataclass],
|
296
|
+
/,
|
297
|
+
*,
|
298
|
+
globalns: StrMapping | None = None,
|
299
|
+
localns: StrMapping | None = None,
|
300
|
+
case_sensitive: bool = False,
|
301
|
+
) -> TDataclass:
|
302
|
+
"""Construct a dataclass from a string or a mapping or strings."""
|
303
|
+
fields = list(yield_fields(cls, globalns=globalns, localns=localns))
|
304
|
+
match text_or_mapping:
|
305
|
+
case str() as text:
|
306
|
+
text_mapping = _text_to_dataclass_split_text(text, cls)
|
307
|
+
case Mapping() as text_mapping:
|
308
|
+
...
|
309
|
+
case _ as never:
|
310
|
+
assert_never(never)
|
311
|
+
value_mapping = dict(
|
312
|
+
_text_to_dataclass_get_and_parse(
|
313
|
+
fields, key, value, cls, case_sensitive=case_sensitive
|
314
|
+
)
|
315
|
+
for key, value in text_mapping.items()
|
316
|
+
)
|
317
|
+
return mapping_to_dataclass(
|
318
|
+
cls,
|
319
|
+
value_mapping,
|
320
|
+
globalns=globalns,
|
321
|
+
localns=localns,
|
322
|
+
case_sensitive=case_sensitive,
|
323
|
+
)
|
324
|
+
|
325
|
+
|
326
|
+
def _text_to_dataclass_split_text(
|
327
|
+
text: str, cls: type[TDataclass], /
|
328
|
+
) -> Mapping[str, str]:
|
329
|
+
pairs = (t for t in text.split(",") if t != "")
|
330
|
+
return dict(_text_to_dataclass_split_key_value_pair(pair, cls) for pair in pairs)
|
331
|
+
|
332
|
+
|
333
|
+
def _text_to_dataclass_split_key_value_pair(
|
334
|
+
text: str, cls: type[Dataclass], /
|
335
|
+
) -> tuple[str, str]:
|
336
|
+
try:
|
337
|
+
key, value = text.split("=")
|
338
|
+
except ValueError:
|
339
|
+
raise _TextToDataClassSplitKeyValuePairError(cls=cls, text=text) from None
|
340
|
+
return key, value
|
341
|
+
|
342
|
+
|
343
|
+
def _text_to_dataclass_get_and_parse(
|
344
|
+
fields: Iterable[_YieldFieldsClass[Any]],
|
345
|
+
key: str,
|
346
|
+
value: str,
|
347
|
+
cls: type[Dataclass],
|
348
|
+
/,
|
349
|
+
*,
|
350
|
+
case_sensitive: bool = False,
|
351
|
+
) -> tuple[str, Any]:
|
352
|
+
mapping = {f.name: f for f in fields}
|
353
|
+
try:
|
354
|
+
name = one_str(mapping, key, head=True, case_sensitive=case_sensitive)
|
355
|
+
except OneStrEmptyError:
|
356
|
+
raise _TextToDataClassGetFieldEmptyError(
|
357
|
+
cls=cls, key=key, case_sensitive=case_sensitive
|
358
|
+
) from None
|
359
|
+
except OneStrNonUniqueError as error:
|
360
|
+
raise _TextToDataClassGetFieldNonUniqueError(
|
361
|
+
cls=cls,
|
362
|
+
key=key,
|
363
|
+
case_sensitive=case_sensitive,
|
364
|
+
first=error.first,
|
365
|
+
second=error.second,
|
366
|
+
) from None
|
367
|
+
field = mapping[name]
|
368
|
+
try:
|
369
|
+
parsed = parse_text(field.type_, value, case_sensitive=case_sensitive)
|
370
|
+
except ParseTextError:
|
371
|
+
raise _TextToDataClassParseValueError(
|
372
|
+
cls=cls, field=field, text=value
|
373
|
+
) from None
|
374
|
+
return key, parsed
|
375
|
+
|
376
|
+
|
377
|
+
@dataclass(kw_only=True, slots=True)
|
378
|
+
class TextToDataClassError(Exception, Generic[TDataclass]):
|
379
|
+
cls: type[TDataclass]
|
380
|
+
|
381
|
+
|
382
|
+
@dataclass(kw_only=True, slots=True)
|
383
|
+
class _TextToDataClassSplitKeyValuePairError(TextToDataClassError):
|
384
|
+
text: str
|
385
|
+
|
386
|
+
@override
|
387
|
+
def __str__(self) -> str:
|
388
|
+
return f"Unable to construct {get_class_name(self.cls)!r}; failed to split key-value pair {self.text!r}"
|
389
|
+
|
390
|
+
|
391
|
+
@dataclass(kw_only=True, slots=True)
|
392
|
+
class _TextToDataClassGetFieldEmptyError(TextToDataClassError[TDataclass]):
|
393
|
+
key: str
|
394
|
+
case_sensitive: bool = False
|
395
|
+
|
396
|
+
@override
|
397
|
+
def __str__(self) -> str:
|
398
|
+
desc = f"Dataclass {get_class_name(self.cls)!r} does not contain any field starting with {self.key!r}"
|
399
|
+
return desc if self.case_sensitive else f"{desc} (modulo case)"
|
400
|
+
|
401
|
+
|
402
|
+
@dataclass(kw_only=True, slots=True)
|
403
|
+
class _TextToDataClassGetFieldNonUniqueError(TextToDataClassError[TDataclass]):
|
404
|
+
key: str
|
405
|
+
case_sensitive: bool = False
|
406
|
+
first: str
|
407
|
+
second: str
|
408
|
+
|
409
|
+
@override
|
410
|
+
def __str__(self) -> str:
|
411
|
+
head = f"Dataclass {get_class_name(self.cls)!r} must contain exactly one field starting with {self.key!r}"
|
412
|
+
mid = "" if self.case_sensitive else " (modulo case)"
|
413
|
+
return f"{head}{mid}; got {self.first!r}, {self.second!r} and perhaps more"
|
414
|
+
|
415
|
+
|
416
|
+
@dataclass(kw_only=True, slots=True)
|
417
|
+
class _TextToDataClassParseValueError(TextToDataClassError[TDataclass]):
|
418
|
+
field: _YieldFieldsClass[Any]
|
419
|
+
text: str
|
420
|
+
|
421
|
+
@override
|
422
|
+
def __str__(self) -> str:
|
423
|
+
return f"Unable to construct {get_class_name(self.cls)!r}; unable to parse field {self.field.name!r} of type {self.field.type_!r}; got {self.text!r}"
|
424
|
+
|
425
|
+
|
426
|
+
##
|
427
|
+
|
428
|
+
|
283
429
|
@overload
|
284
430
|
def yield_fields(
|
285
431
|
obj: Dataclass,
|
@@ -346,18 +492,18 @@ def yield_fields(
|
|
346
492
|
raise YieldFieldsError(obj=obj)
|
347
493
|
|
348
494
|
|
349
|
-
@dataclass(kw_only=True, slots=True)
|
495
|
+
@dataclass(order=True, unsafe_hash=True, kw_only=True, slots=True)
|
350
496
|
class _YieldFieldsInstance(Generic[_T]):
|
351
497
|
name: str
|
352
|
-
value: _T
|
353
|
-
type_: Any
|
354
|
-
default: _T | Sentinel = sentinel
|
355
|
-
default_factory: Callable[[], _T] | Sentinel = sentinel
|
498
|
+
value: _T = field(hash=False)
|
499
|
+
type_: Any = field(hash=False)
|
500
|
+
default: _T | Sentinel = field(default=sentinel, hash=False)
|
501
|
+
default_factory: Callable[[], _T] | Sentinel = field(default=sentinel, hash=False)
|
356
502
|
repr: bool = True
|
357
503
|
hash_: bool | None = None
|
358
504
|
init: bool = True
|
359
505
|
compare: bool = True
|
360
|
-
metadata: StrMapping = field(default_factory=dict)
|
506
|
+
metadata: StrMapping = field(default_factory=dict, hash=False)
|
361
507
|
kw_only: bool | Sentinel = sentinel
|
362
508
|
|
363
509
|
def equals_default(
|
@@ -407,17 +553,17 @@ class _YieldFieldsInstance(Generic[_T]):
|
|
407
553
|
return (defaults and equal) or not equal
|
408
554
|
|
409
555
|
|
410
|
-
@dataclass(kw_only=True, slots=True)
|
556
|
+
@dataclass(order=True, unsafe_hash=True, kw_only=True, slots=True)
|
411
557
|
class _YieldFieldsClass(Generic[_T]):
|
412
558
|
name: str
|
413
|
-
type_: Any
|
414
|
-
default: _T | Sentinel = sentinel
|
415
|
-
default_factory: Callable[[], _T] | Sentinel = sentinel
|
559
|
+
type_: Any = field(hash=False)
|
560
|
+
default: _T | Sentinel = field(default=sentinel, hash=False)
|
561
|
+
default_factory: Callable[[], _T] | Sentinel = field(default=sentinel, hash=False)
|
416
562
|
repr: bool = True
|
417
563
|
hash_: bool | None = None
|
418
564
|
init: bool = True
|
419
565
|
compare: bool = True
|
420
|
-
metadata: StrMapping = field(default_factory=dict)
|
566
|
+
metadata: StrMapping = field(default_factory=dict, hash=False)
|
421
567
|
kw_only: bool | Sentinel = sentinel
|
422
568
|
|
423
569
|
|
@@ -434,10 +580,12 @@ class YieldFieldsError(Exception):
|
|
434
580
|
|
435
581
|
__all__ = [
|
436
582
|
"MappingToDataclassError",
|
583
|
+
"TextToDataClassError",
|
437
584
|
"YieldFieldsError",
|
438
585
|
"dataclass_repr",
|
439
586
|
"dataclass_to_dict",
|
440
587
|
"mapping_to_dataclass",
|
441
588
|
"replace_non_sentinel",
|
589
|
+
"text_to_dataclass",
|
442
590
|
"yield_fields",
|
443
591
|
]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_missing/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_missing/module.py
RENAMED
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_with/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_without/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_without/module_1.py
RENAMED
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/modules/package_without/module_2.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_async_service/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_async_service/__main__.py
RENAMED
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_async_service/run.sh
RENAMED
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_queue_processor/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_queue_processor/__main__.py
RENAMED
File without changes
|
{dycw_utilities-0.108.3 → dycw_utilities-0.108.4}/src/tests/scripts/test_queue_processor/run.sh
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|