dycw-utilities 0.109.2__tar.gz → 0.109.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.109.2 → dycw_utilities-0.109.4}/PKG-INFO +1 -1
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/pyproject.toml +2 -2
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_parse.py +90 -17
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_typing.py +44 -5
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/__init__.py +1 -1
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/parse.py +77 -22
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/typing.py +9 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/.gitignore +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/LICENSE +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/README.md +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/__init__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/conftest.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/__init__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_missing/__init__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_missing/module.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_with/__init__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_with/outer_1.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_with/outer_2.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_without/__init__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_without/module_1.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_without/module_2.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/standalone.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/with_imports.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/__init__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/test_async_service/__init__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/test_async_service/__main__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/test_async_service/run.sh +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/test_queue_processor/__init__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/test_queue_processor/__main__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/test_queue_processor/run.sh +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_altair.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_astor.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_asyncio.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_atomicwrites.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_atools.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_cachetools.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_click.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_concurrent.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_contextlib.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_contextvars.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_cryptography.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_cvxpy.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_dataclasses.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_datetime.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_enum.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_errors.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_eventkit.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_fastapi.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_fpdf2.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_functions.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_functools.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_getpass.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_git.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_hashlib.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_http.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_hypothesis.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_ipython.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_iterables.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_jupyter.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_logging.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_loguru.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_luigi.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_math.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_memory_profiler.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_modules.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_more_itertools.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_numpy.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_operator.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_optuna.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_orjson.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_os.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_pathlib.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_period.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_pickle.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_platform.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_polars.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_pqdm.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_pydantic.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_pyinstrument.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_pyrsistent.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_pytest.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_pytest_regressions.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_python_dotenv.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_random.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_re.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_redis.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_reprlib.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_rich.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_scipy.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_sentinel.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_shelve.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_slack_sdk.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_socket.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_sqlalchemy.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_streamlit.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_sys.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_tempfile.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_tenacity.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_text.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_threading.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_timer.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/__init__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/chain.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/decorated_async.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/decorated_sync.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/error_bind.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/many.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/one.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/recursive.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/task_group_one.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/task_group_two.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/two.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_traceback_funcs/untraced.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_types.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_typing_funcs/__init__.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_typing_funcs/no_future.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_typing_funcs/with_future.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_tzdata.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_tzlocal.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_uuid.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_version.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_warnings.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_whenever.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_zipfile.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/test_zoneinfo.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/altair.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/astor.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/asyncio.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/atomicwrites.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/atools.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/cachetools.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/click.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/concurrent.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/contextlib.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/contextvars.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/cryptography.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/cvxpy.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/dataclasses.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/datetime.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/enum.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/errors.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/eventkit.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/fastapi.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/fpdf2.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/functions.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/functools.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/getpass.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/git.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/hashlib.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/http.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/hypothesis.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/ipython.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/iterables.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/jupyter.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/logging.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/loguru.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/luigi.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/math.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/memory_profiler.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/modules.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/more_itertools.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/numpy.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/operator.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/optuna.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/orjson.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/os.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/pathlib.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/period.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/pickle.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/platform.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/polars.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/pqdm.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/py.typed +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/pydantic.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/pyinstrument.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/pyrsistent.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/pytest.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/pytest_regressions.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/python_dotenv.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/random.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/re.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/redis.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/reprlib.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/rich.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/scipy.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/sentinel.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/shelve.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/slack_sdk.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/socket.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/sqlalchemy.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/streamlit.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/sys.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/tempfile.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/tenacity.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/text.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/threading.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/timer.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/traceback.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/types.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/tzdata.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/tzlocal.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/uuid.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/version.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/warnings.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/whenever.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/zipfile.py +0 -0
- {dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/utilities/zoneinfo.py +0 -0
@@ -89,7 +89,7 @@ dependencies = [
|
|
89
89
|
name = "dycw-utilities"
|
90
90
|
readme = "README.md"
|
91
91
|
requires-python = ">= 3.12"
|
92
|
-
version = "0.109.
|
92
|
+
version = "0.109.4"
|
93
93
|
|
94
94
|
[project.optional-dependencies]
|
95
95
|
test = [
|
@@ -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.109.
|
335
|
+
current_version = "0.109.4"
|
336
336
|
|
337
337
|
[[tool.bumpversion.files]]
|
338
338
|
filename = "src/utilities/__init__.py"
|
@@ -13,6 +13,7 @@ from pytest import raises
|
|
13
13
|
|
14
14
|
from tests.test_operator import TruthEnum
|
15
15
|
from tests.test_typing_funcs.with_future import (
|
16
|
+
DataClassFutureInt,
|
16
17
|
TrueOrFalseFutureLit,
|
17
18
|
TrueOrFalseFutureTypeLit,
|
18
19
|
)
|
@@ -26,7 +27,11 @@ from utilities.hypothesis import (
|
|
26
27
|
zoned_datetimes,
|
27
28
|
)
|
28
29
|
from utilities.math import is_equal
|
29
|
-
from utilities.parse import
|
30
|
+
from utilities.parse import (
|
31
|
+
_ParseTextExtraNonUniqueError,
|
32
|
+
_ParseTextParseError,
|
33
|
+
parse_text,
|
34
|
+
)
|
30
35
|
from utilities.sentinel import Sentinel, sentinel
|
31
36
|
from utilities.version import Version
|
32
37
|
from utilities.whenever import (
|
@@ -62,6 +67,17 @@ class TestParseText:
|
|
62
67
|
result = parse_text(TruthEnum, text)
|
63
68
|
assert result is truth
|
64
69
|
|
70
|
+
@given(value=integers())
|
71
|
+
def test_extra(self, *, value: int) -> None:
|
72
|
+
text = str(value)
|
73
|
+
result = parse_text(
|
74
|
+
DataClassFutureInt,
|
75
|
+
text,
|
76
|
+
extra={DataClassFutureInt: lambda text: DataClassFutureInt(int_=int(text))},
|
77
|
+
)
|
78
|
+
expected = DataClassFutureInt(int_=value)
|
79
|
+
assert result == expected
|
80
|
+
|
65
81
|
@given(value=floats())
|
66
82
|
def test_float(self, *, value: float) -> None:
|
67
83
|
text = str(value)
|
@@ -135,6 +151,12 @@ class TestParseText:
|
|
135
151
|
result = parse_text(dt.timedelta, text)
|
136
152
|
assert result == timedelta
|
137
153
|
|
154
|
+
@given(x=integers(), y=integers())
|
155
|
+
def test_tuple(self, *, x: int, y: int) -> None:
|
156
|
+
text = f"({x}, {y})"
|
157
|
+
result = parse_text(tuple[int, int], text)
|
158
|
+
assert result == (x, y)
|
159
|
+
|
138
160
|
@given(truth=sampled_from(["true", "false"]))
|
139
161
|
def test_type_literal(self, *, truth: Literal["true", "false"]) -> None:
|
140
162
|
result = parse_text(TrueOrFalseFutureTypeLit, truth)
|
@@ -148,88 +170,139 @@ class TestParseText:
|
|
148
170
|
|
149
171
|
def test_error_bool(self) -> None:
|
150
172
|
with raises(
|
151
|
-
|
173
|
+
_ParseTextParseError, match="Unable to parse <class 'bool'>; got 'invalid'"
|
152
174
|
):
|
153
175
|
_ = parse_text(bool, "invalid")
|
154
176
|
|
155
177
|
def test_error_date(self) -> None:
|
156
178
|
with raises(
|
157
|
-
|
179
|
+
_ParseTextParseError,
|
158
180
|
match=r"Unable to parse <class 'datetime\.date'>; got 'invalid'",
|
159
181
|
):
|
160
182
|
_ = parse_text(dt.date, "invalid")
|
161
183
|
|
162
184
|
def test_error_datetime(self) -> None:
|
163
185
|
with raises(
|
164
|
-
|
186
|
+
_ParseTextParseError,
|
165
187
|
match=r"Unable to parse <class 'datetime\.datetime'>; got 'invalid'",
|
166
188
|
):
|
167
189
|
_ = parse_text(dt.datetime, "invalid")
|
168
190
|
|
169
191
|
def test_error_enum(self) -> None:
|
170
192
|
with raises(
|
171
|
-
|
193
|
+
_ParseTextParseError,
|
194
|
+
match="Unable to parse <enum 'TruthEnum'>; got 'invalid'",
|
172
195
|
):
|
173
196
|
_ = parse_text(TruthEnum, "invalid")
|
174
197
|
|
198
|
+
def test_error_extra_empty(self) -> None:
|
199
|
+
with raises(
|
200
|
+
_ParseTextParseError,
|
201
|
+
match="Unable to parse <class 'tests.test_typing_funcs.with_future.DataClassFutureInt'>; got 'invalid'",
|
202
|
+
):
|
203
|
+
_ = parse_text(DataClassFutureInt, "invalid", extra={})
|
204
|
+
|
205
|
+
@given(value=integers())
|
206
|
+
def test_error_extra_non_unique(self, *, value: int) -> None:
|
207
|
+
@dataclass(kw_only=True)
|
208
|
+
class Parent1:
|
209
|
+
x: int = 0
|
210
|
+
|
211
|
+
@dataclass(kw_only=True)
|
212
|
+
class Parent2:
|
213
|
+
y: int = 0
|
214
|
+
|
215
|
+
@dataclass(kw_only=True)
|
216
|
+
class Child(Parent1, Parent2): ...
|
217
|
+
|
218
|
+
with raises(
|
219
|
+
_ParseTextExtraNonUniqueError,
|
220
|
+
match="Unable to parse <class '.*'> since `extra` must contain exactly one parent class; got <function .*>, <function .*> and perhaps more",
|
221
|
+
):
|
222
|
+
_ = parse_text(
|
223
|
+
Child,
|
224
|
+
str(value),
|
225
|
+
extra={
|
226
|
+
Parent1: lambda text: Child(x=int(text)),
|
227
|
+
Parent2: lambda text: Child(y=int(text)),
|
228
|
+
},
|
229
|
+
)
|
230
|
+
|
175
231
|
def test_error_float(self) -> None:
|
176
232
|
with raises(
|
177
|
-
|
233
|
+
_ParseTextParseError, match="Unable to parse <class 'float'>; got 'invalid'"
|
178
234
|
):
|
179
235
|
_ = parse_text(float, "invalid")
|
180
236
|
|
181
237
|
def test_error_int(self) -> None:
|
182
238
|
with raises(
|
183
|
-
|
239
|
+
_ParseTextParseError, match="Unable to parse <class 'int'>; got 'invalid'"
|
184
240
|
):
|
185
241
|
_ = parse_text(int, "invalid")
|
186
242
|
|
187
243
|
def test_error_none(self) -> None:
|
188
|
-
with raises(
|
244
|
+
with raises(_ParseTextParseError, match="Unable to parse None; got 'invalid'"):
|
189
245
|
_ = parse_text(None, "invalid")
|
190
246
|
|
191
247
|
def test_error_none_type(self) -> None:
|
192
248
|
with raises(
|
193
|
-
|
249
|
+
_ParseTextParseError,
|
250
|
+
match="Unable to parse <class 'NoneType'>; got 'invalid'",
|
194
251
|
):
|
195
252
|
_ = parse_text(NoneType, "invalid")
|
196
253
|
|
197
254
|
def test_error_nullable_int(self) -> None:
|
198
255
|
with raises(
|
199
|
-
|
256
|
+
_ParseTextParseError, match=r"Unable to parse int \| None; got 'invalid'"
|
200
257
|
):
|
201
258
|
_ = parse_text(int | None, "invalid")
|
202
259
|
|
203
260
|
def test_error_nullable_not_type(self) -> None:
|
204
261
|
with raises(
|
205
|
-
|
262
|
+
_ParseTextParseError,
|
206
263
|
match=r"Unable to parse collections\.abc\.Iterable\[None\] \| None; got 'invalid'",
|
207
264
|
):
|
208
265
|
_ = parse_text(Iterable[None] | None, "invalid")
|
209
266
|
|
210
267
|
def test_error_sentinel(self) -> None:
|
211
268
|
with raises(
|
212
|
-
|
269
|
+
_ParseTextParseError,
|
213
270
|
match=r"Unable to parse <class 'utilities\.sentinel\.Sentinel'>; got 'invalid'",
|
214
271
|
):
|
215
272
|
_ = parse_text(Sentinel, "invalid")
|
216
273
|
|
217
274
|
def test_error_time(self) -> None:
|
218
275
|
with raises(
|
219
|
-
|
276
|
+
_ParseTextParseError,
|
220
277
|
match=r"Unable to parse <class 'datetime\.time'>; got 'invalid'",
|
221
278
|
):
|
222
279
|
_ = parse_text(dt.time, "invalid")
|
223
280
|
|
224
281
|
def test_error_timedelta(self) -> None:
|
225
282
|
with raises(
|
226
|
-
|
283
|
+
_ParseTextParseError,
|
227
284
|
match=r"Unable to parse <class 'datetime\.timedelta'>; got 'invalid'",
|
228
285
|
):
|
229
286
|
_ = parse_text(dt.timedelta, "invalid")
|
230
287
|
|
288
|
+
def test_error_tuple_invalid_text(self) -> None:
|
289
|
+
with raises(
|
290
|
+
_ParseTextParseError,
|
291
|
+
match=r"Unable to parse tuple\[int, int\]; got 'invalid'",
|
292
|
+
):
|
293
|
+
_ = parse_text(tuple[int, int], "invalid")
|
294
|
+
|
295
|
+
def test_error_tuple_inconsistent_args_and_texts(self) -> None:
|
296
|
+
with raises(
|
297
|
+
_ParseTextParseError,
|
298
|
+
match=r"Unable to parse tuple\[int, int\]; got '\(text1, text2, text3\)'",
|
299
|
+
):
|
300
|
+
_ = parse_text(tuple[int, int], "(text1, text2, text3)")
|
301
|
+
|
231
302
|
def test_error_unknown_annotation(self) -> None:
|
232
|
-
with raises(
|
303
|
+
with raises(
|
304
|
+
_ParseTextParseError, match=r"Unable to parse int \| str; got 'invalid'"
|
305
|
+
):
|
233
306
|
_ = parse_text(int | str, "invalid")
|
234
307
|
|
235
308
|
def test_error_unknown_type(self) -> None:
|
@@ -238,14 +311,14 @@ class TestParseText:
|
|
238
311
|
pass
|
239
312
|
|
240
313
|
with raises(
|
241
|
-
|
314
|
+
_ParseTextParseError,
|
242
315
|
match=r"Unable to parse <class 'tests\.test_parse\.TestParseText\.test_error_unknown_type\.<locals>\.Example'>; got 'invalid'",
|
243
316
|
):
|
244
317
|
_ = parse_text(Example, "invalid")
|
245
318
|
|
246
319
|
def test_error_version(self) -> None:
|
247
320
|
with raises(
|
248
|
-
|
321
|
+
_ParseTextParseError,
|
249
322
|
match=r"Unable to parse <class 'utilities\.version\.Version'>; got 'invalid'",
|
250
323
|
):
|
251
324
|
_ = parse_text(Version, "invalid")
|
@@ -55,6 +55,7 @@ from utilities.typing import (
|
|
55
55
|
is_optional_type,
|
56
56
|
is_sequence_type,
|
57
57
|
is_set_type,
|
58
|
+
is_tuple_type,
|
58
59
|
is_union_type,
|
59
60
|
)
|
60
61
|
|
@@ -338,25 +339,63 @@ class TestIsAnnotationOfType:
|
|
338
339
|
@mark.parametrize(
|
339
340
|
("func", "obj", "expected"),
|
340
341
|
[
|
342
|
+
param(is_dict_type, Mapping[int, int], False),
|
343
|
+
param(is_dict_type, Sequence[int], False),
|
341
344
|
param(is_dict_type, dict[int, int], True),
|
345
|
+
param(is_dict_type, frozenset[int], False),
|
342
346
|
param(is_dict_type, list[int], False),
|
347
|
+
param(is_dict_type, set[int], False),
|
348
|
+
param(is_dict_type, tuple[int, int], False),
|
349
|
+
param(is_frozenset_type, Mapping[int, int], False),
|
350
|
+
param(is_frozenset_type, Sequence[int], False),
|
351
|
+
param(is_frozenset_type, dict[int, int], False),
|
343
352
|
param(is_frozenset_type, frozenset[int], True),
|
344
353
|
param(is_frozenset_type, list[int], False),
|
354
|
+
param(is_frozenset_type, set[int], False),
|
355
|
+
param(is_frozenset_type, tuple[int, int], False),
|
356
|
+
param(is_list_type, Mapping[int, int], False),
|
357
|
+
param(is_list_type, Sequence[int], False),
|
358
|
+
param(is_list_type, dict[int, int], False),
|
359
|
+
param(is_list_type, frozenset[int], False),
|
345
360
|
param(is_list_type, list[int], True),
|
346
361
|
param(is_list_type, set[int], False),
|
347
|
-
param(
|
348
|
-
param(is_mapping_type, list[int], False),
|
362
|
+
param(is_list_type, tuple[int, int], False),
|
349
363
|
param(is_literal_type, Literal["a", "b", "c"], True),
|
350
364
|
param(is_literal_type, list[int], False),
|
365
|
+
param(is_mapping_type, Mapping[int, int], True),
|
366
|
+
param(is_mapping_type, Sequence[int], False),
|
367
|
+
param(is_mapping_type, dict[int, int], False),
|
368
|
+
param(is_mapping_type, frozenset[int], False),
|
369
|
+
param(is_mapping_type, list[int], False),
|
370
|
+
param(is_mapping_type, set[int], False),
|
371
|
+
param(is_mapping_type, tuple[int, int], False),
|
372
|
+
param(is_optional_type, Literal["a", "b", "c"] | None, True),
|
373
|
+
param(is_optional_type, Literal["a", "b", "c"], False),
|
351
374
|
param(is_optional_type, int | None, True),
|
352
375
|
param(is_optional_type, int | str, False),
|
353
|
-
param(is_optional_type, list[int], False),
|
354
376
|
param(is_optional_type, list[int] | None, True),
|
355
|
-
param(is_optional_type,
|
356
|
-
param(
|
377
|
+
param(is_optional_type, list[int], False),
|
378
|
+
param(is_sequence_type, Mapping[int, int], False),
|
357
379
|
param(is_sequence_type, Sequence[int], True),
|
380
|
+
param(is_sequence_type, dict[int, int], False),
|
381
|
+
param(is_sequence_type, frozenset[int], False),
|
358
382
|
param(is_sequence_type, list[int], False),
|
383
|
+
param(is_sequence_type, set[int], False),
|
384
|
+
param(is_sequence_type, tuple[int, int], False),
|
385
|
+
param(is_set_type, Mapping[int, int], False),
|
386
|
+
param(is_set_type, Sequence[int], False),
|
387
|
+
param(is_set_type, dict[int, int], False),
|
388
|
+
param(is_set_type, frozenset[int], False),
|
359
389
|
param(is_set_type, list[int], False),
|
390
|
+
param(is_set_type, set[int], True),
|
391
|
+
param(is_set_type, tuple[int, int], False),
|
392
|
+
param(is_tuple_type, Mapping[int, int], False),
|
393
|
+
param(is_tuple_type, Sequence[int], False),
|
394
|
+
param(is_tuple_type, dict[int, int], False),
|
395
|
+
param(is_tuple_type, frozenset[int], False),
|
396
|
+
param(is_tuple_type, list[int], False),
|
397
|
+
param(is_tuple_type, set[int], False),
|
398
|
+
param(is_tuple_type, tuple[int, int], True),
|
360
399
|
param(is_union_type, int | str, True),
|
361
400
|
param(is_union_type, list[int], False),
|
362
401
|
],
|
@@ -5,30 +5,44 @@ from contextlib import suppress
|
|
5
5
|
from dataclasses import dataclass
|
6
6
|
from enum import Enum
|
7
7
|
from pathlib import Path
|
8
|
+
from re import DOTALL
|
8
9
|
from types import NoneType
|
9
|
-
from typing import Any, override
|
10
|
+
from typing import TYPE_CHECKING, Any, TypeVar, override
|
10
11
|
|
11
12
|
from utilities.datetime import is_subclass_date_not_datetime
|
12
13
|
from utilities.enum import ParseEnumError, parse_enum
|
13
14
|
from utilities.functions import is_subclass_int_not_bool
|
14
|
-
from utilities.iterables import one, one_str
|
15
|
+
from utilities.iterables import OneEmptyError, OneNonUniqueError, one, one_str
|
16
|
+
from utilities.re import ExtractGroupError, extract_group
|
15
17
|
from utilities.sentinel import ParseSentinelError, Sentinel, parse_sentinel
|
16
18
|
from utilities.text import ParseBoolError, ParseNoneError, parse_bool, parse_none
|
17
|
-
from utilities.typing import get_args, is_literal_type, is_optional_type
|
19
|
+
from utilities.typing import get_args, is_literal_type, is_optional_type, is_tuple_type
|
18
20
|
from utilities.version import ParseVersionError, Version, parse_version
|
19
21
|
|
22
|
+
if TYPE_CHECKING:
|
23
|
+
from collections.abc import Callable, Mapping
|
24
|
+
|
25
|
+
|
26
|
+
_T = TypeVar("_T")
|
27
|
+
|
20
28
|
|
21
29
|
def parse_text(
|
22
|
-
obj: Any,
|
30
|
+
obj: Any,
|
31
|
+
text: str,
|
32
|
+
/,
|
33
|
+
*,
|
34
|
+
case_sensitive: bool = False,
|
35
|
+
head: bool = False,
|
36
|
+
extra: Mapping[type[_T], Callable[[str], _T]] | None = None,
|
23
37
|
) -> Any:
|
24
38
|
"""Parse text."""
|
25
39
|
if obj is None:
|
26
40
|
try:
|
27
41
|
return parse_none(text)
|
28
42
|
except ParseNoneError:
|
29
|
-
raise
|
43
|
+
raise _ParseTextParseError(obj=obj, text=text) from None
|
30
44
|
if isinstance(obj, type):
|
31
|
-
return _parse_text_type(obj, text, case_sensitive=case_sensitive)
|
45
|
+
return _parse_text_type(obj, text, case_sensitive=case_sensitive, extra=extra)
|
32
46
|
if is_literal_type(obj):
|
33
47
|
return one_str(get_args(obj), text, head=head, case_sensitive=case_sensitive)
|
34
48
|
if is_optional_type(obj):
|
@@ -40,83 +54,111 @@ def parse_text(
|
|
40
54
|
):
|
41
55
|
try:
|
42
56
|
return _parse_text_type(inner, text, case_sensitive=case_sensitive)
|
43
|
-
except
|
44
|
-
raise
|
45
|
-
|
57
|
+
except _ParseTextParseError:
|
58
|
+
raise _ParseTextParseError(obj=obj, text=text) from None
|
59
|
+
if is_tuple_type(obj):
|
60
|
+
args = get_args(obj)
|
61
|
+
try:
|
62
|
+
texts = extract_group(r"^\((.*)\)$", text, flags=DOTALL).split(", ")
|
63
|
+
except ExtractGroupError:
|
64
|
+
raise _ParseTextParseError(obj=obj, text=text) from None
|
65
|
+
if len(args) != len(texts):
|
66
|
+
raise _ParseTextParseError(obj=obj, text=text)
|
67
|
+
return tuple(
|
68
|
+
parse_text(arg, text, case_sensitive=case_sensitive, head=head)
|
69
|
+
for arg, text in zip(args, texts, strict=True)
|
70
|
+
)
|
71
|
+
raise _ParseTextParseError(obj=obj, text=text) from None
|
46
72
|
|
47
73
|
|
48
74
|
def _parse_text_type(
|
49
|
-
cls: type[Any],
|
75
|
+
cls: type[Any],
|
76
|
+
text: str,
|
77
|
+
/,
|
78
|
+
*,
|
79
|
+
case_sensitive: bool = False,
|
80
|
+
extra: Mapping[type[_T], Callable[[str], _T]] | None = None,
|
50
81
|
) -> Any:
|
51
82
|
"""Parse text."""
|
52
83
|
if issubclass(cls, NoneType):
|
53
84
|
try:
|
54
85
|
return parse_none(text)
|
55
86
|
except ParseNoneError:
|
56
|
-
raise
|
87
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
57
88
|
if issubclass(cls, str):
|
58
89
|
return text
|
59
90
|
if issubclass(cls, bool):
|
60
91
|
try:
|
61
92
|
return parse_bool(text)
|
62
93
|
except ParseBoolError:
|
63
|
-
raise
|
94
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
64
95
|
if is_subclass_int_not_bool(cls):
|
65
96
|
try:
|
66
97
|
return int(text)
|
67
98
|
except ValueError:
|
68
|
-
raise
|
99
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
69
100
|
if issubclass(cls, float):
|
70
101
|
try:
|
71
102
|
return float(text)
|
72
103
|
except ValueError:
|
73
|
-
raise
|
104
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
74
105
|
if issubclass(cls, Enum):
|
75
106
|
try:
|
76
107
|
return parse_enum(text, cls, case_sensitive=case_sensitive)
|
77
108
|
except ParseEnumError:
|
78
|
-
raise
|
109
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
79
110
|
if issubclass(cls, Path):
|
80
111
|
return Path(text).expanduser()
|
81
112
|
if issubclass(cls, Sentinel):
|
82
113
|
try:
|
83
114
|
return parse_sentinel(text)
|
84
115
|
except ParseSentinelError:
|
85
|
-
raise
|
116
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
86
117
|
if issubclass(cls, Version):
|
87
118
|
try:
|
88
119
|
return parse_version(text)
|
89
120
|
except ParseVersionError:
|
90
|
-
raise
|
121
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
91
122
|
if is_subclass_date_not_datetime(cls):
|
92
123
|
from utilities.whenever import ParseDateError, parse_date
|
93
124
|
|
94
125
|
try:
|
95
126
|
return parse_date(text)
|
96
127
|
except ParseDateError:
|
97
|
-
raise
|
128
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
98
129
|
if issubclass(cls, dt.datetime):
|
99
130
|
from utilities.whenever import ParseDateTimeError, parse_datetime
|
100
131
|
|
101
132
|
try:
|
102
133
|
return parse_datetime(text)
|
103
134
|
except ParseDateTimeError:
|
104
|
-
raise
|
135
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
105
136
|
if issubclass(cls, dt.time):
|
106
137
|
from utilities.whenever import ParseTimeError, parse_time
|
107
138
|
|
108
139
|
try:
|
109
140
|
return parse_time(text)
|
110
141
|
except ParseTimeError:
|
111
|
-
raise
|
142
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
112
143
|
if issubclass(cls, dt.timedelta):
|
113
144
|
from utilities.whenever import ParseTimedeltaError, parse_timedelta
|
114
145
|
|
115
146
|
try:
|
116
147
|
return parse_timedelta(text)
|
117
148
|
except ParseTimedeltaError:
|
118
|
-
raise
|
119
|
-
|
149
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
150
|
+
if extra is not None:
|
151
|
+
try:
|
152
|
+
parser = one(p for c, p in extra.items() if issubclass(cls, c))
|
153
|
+
except OneEmptyError:
|
154
|
+
pass
|
155
|
+
except OneNonUniqueError as error:
|
156
|
+
raise _ParseTextExtraNonUniqueError(
|
157
|
+
obj=cls, text=text, first=error.first, second=error.second
|
158
|
+
) from None
|
159
|
+
else:
|
160
|
+
return parser(text)
|
161
|
+
raise _ParseTextParseError(obj=cls, text=text) from None
|
120
162
|
|
121
163
|
|
122
164
|
@dataclass
|
@@ -124,6 +166,19 @@ class ParseTextError(Exception):
|
|
124
166
|
obj: Any
|
125
167
|
text: str
|
126
168
|
|
169
|
+
|
170
|
+
@dataclass
|
171
|
+
class _ParseTextParseError(ParseTextError):
|
127
172
|
@override
|
128
173
|
def __str__(self) -> str:
|
129
174
|
return f"Unable to parse {self.obj!r}; got {self.text!r}"
|
175
|
+
|
176
|
+
|
177
|
+
@dataclass
|
178
|
+
class _ParseTextExtraNonUniqueError(ParseTextError):
|
179
|
+
first: type[Any]
|
180
|
+
second: type[Any]
|
181
|
+
|
182
|
+
@override
|
183
|
+
def __str__(self) -> str:
|
184
|
+
return f"Unable to parse {self.obj!r} since `extra` must contain exactly one parent class; got {self.first!r}, {self.second!r} and perhaps more"
|
@@ -182,6 +182,14 @@ def is_set_type(obj: Any, /) -> bool:
|
|
182
182
|
##
|
183
183
|
|
184
184
|
|
185
|
+
def is_tuple_type(obj: Any, /) -> bool:
|
186
|
+
"""Check if an object is a tuple type annotation."""
|
187
|
+
return _is_annotation_of_type(obj, tuple)
|
188
|
+
|
189
|
+
|
190
|
+
##
|
191
|
+
|
192
|
+
|
185
193
|
def is_union_type(obj: Any, /) -> bool:
|
186
194
|
"""Check if an object is a union type annotation."""
|
187
195
|
is_old_union = _is_annotation_of_type(obj, Union) # pyright: ignore[reportDeprecated]
|
@@ -212,5 +220,6 @@ __all__ = [
|
|
212
220
|
"is_optional_type",
|
213
221
|
"is_sequence_type",
|
214
222
|
"is_set_type",
|
223
|
+
"is_tuple_type",
|
215
224
|
"is_union_type",
|
216
225
|
]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_missing/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_missing/module.py
RENAMED
File without changes
|
{dycw_utilities-0.109.2 → dycw_utilities-0.109.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.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_without/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/modules/package_without/module_1.py
RENAMED
File without changes
|
{dycw_utilities-0.109.2 → dycw_utilities-0.109.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.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/test_async_service/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/test_async_service/__main__.py
RENAMED
File without changes
|
{dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/test_async_service/run.sh
RENAMED
File without changes
|
{dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/test_queue_processor/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.109.2 → dycw_utilities-0.109.4}/src/tests/scripts/test_queue_processor/__main__.py
RENAMED
File without changes
|
{dycw_utilities-0.109.2 → dycw_utilities-0.109.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
|