dycw-utilities 0.131.1__tar.gz → 0.131.2__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.131.1 → dycw_utilities-0.131.2}/PKG-INFO +1 -1
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/pyproject.toml +3 -2
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_hypothesis.py +80 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_whenever.py +1 -20
- dycw_utilities-0.131.2/src/tests/test_whenever2.py +194 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/__init__.py +1 -1
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/hypothesis.py +162 -3
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/logging.py +1 -1
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/typing.py +1 -1
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/whenever.py +1 -64
- dycw_utilities-0.131.2/src/utilities/whenever2.py +139 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/.gitignore +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/LICENSE +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/README.md +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/__init__.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/conftest.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/__init__.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_missing/__init__.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_missing/module.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_with/__init__.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_with/outer_1.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_with/outer_2.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_without/__init__.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_without/module_1.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/package_without/module_2.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/standalone.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/modules/with_imports.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_aiolimiter.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_altair.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_asyncio.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_asyncio_classes/__init__.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_asyncio_classes/loopers.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_asyncio_classes/redis.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_atomicwrites.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_atools.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_cachetools.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_click.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_concurrent.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_contextlib.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_contextvars.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_cryptography.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_cvxpy.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_dataclasses.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_datetime.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_enum.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_errors.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_eventkit.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_fastapi.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_fpdf2.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_functions.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_functools.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_getpass.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_git.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_hashlib.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_http.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_importlib.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_inflect.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_ipython.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_iterables.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_jupyter.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_libcst.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_lightweight_charts.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_logging.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_luigi.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_math.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_memory_profiler.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_modules.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_more_itertools.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_numpy.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_operator.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_optuna.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_orjson.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_os.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_parse.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_pathlib.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_period.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_pickle.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_platform.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_polars.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_polars_ols.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_pottery.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_pqdm.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_psutil.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_pydantic.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_pyinstrument.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_pyrsistent.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_pytest.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_pytest_regressions.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_python_dotenv.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_random.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_re.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_redis.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_reprlib.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_scipy.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_sentinel.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_shelve.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_slack_sdk.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_socket.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_sqlalchemy.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_statsmodel.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_streamlit.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_string.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_tempfile.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_tenacity.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_text.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_threading.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_timer.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_traceback.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_types.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_typing.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_typing_funcs/__init__.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_typing_funcs/no_future.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_typing_funcs/with_future.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_tzdata.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_tzlocal.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_uuid.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_version.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_warnings.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_zipfile.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/tests/test_zoneinfo.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/aiolimiter.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/altair.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/asyncio.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/atomicwrites.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/atools.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/cachetools.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/click.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/concurrent.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/contextlib.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/contextvars.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/cryptography.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/cvxpy.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/dataclasses.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/datetime.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/enum.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/errors.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/eventkit.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/fastapi.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/fpdf2.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/functions.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/functools.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/getpass.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/git.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/hashlib.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/http.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/importlib.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/inflect.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/ipython.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/iterables.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/jupyter.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/libcst.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/lightweight_charts.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/luigi.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/math.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/memory_profiler.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/modules.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/more_itertools.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/numpy.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/operator.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/optuna.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/orjson.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/os.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/parse.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/pathlib.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/period.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/pickle.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/platform.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/polars.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/polars_ols.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/pottery.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/pqdm.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/psutil.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/py.typed +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/pydantic.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/pyinstrument.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/pyrsistent.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/pytest.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/pytest_regressions.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/python_dotenv.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/random.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/re.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/redis.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/reprlib.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/scipy.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/sentinel.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/shelve.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/slack_sdk.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/socket.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/sqlalchemy.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/statsmodels.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/streamlit.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/string.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/tempfile.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/tenacity.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/text.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/threading.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/timer.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/traceback.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/types.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/tzdata.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/tzlocal.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/uuid.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/version.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/warnings.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/src/utilities/zipfile.py +0 -0
- {dycw_utilities-0.131.1 → dycw_utilities-0.131.2}/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.131.
|
97
|
+
version = "0.131.2"
|
98
98
|
|
99
99
|
[project.optional-dependencies]
|
100
100
|
logging = [
|
@@ -341,7 +341,7 @@ zzz-test-zoneinfo = [
|
|
341
341
|
# bump-my-version
|
342
342
|
[tool.bumpversion]
|
343
343
|
allow_dirty = true
|
344
|
-
current_version = "0.131.
|
344
|
+
current_version = "0.131.2"
|
345
345
|
|
346
346
|
[[tool.bumpversion.files]]
|
347
347
|
filename = "src/utilities/__init__.py"
|
@@ -354,6 +354,7 @@ search = "__version__ = \"{current_version}\""
|
|
354
354
|
[tool.coverage.coverage_conditional_plugin.rules]
|
355
355
|
skipif-ci = '"CI" in os_environ'
|
356
356
|
skipif-ci-and-not-linux = '("CI" in os_environ) and (sys_platform != "linux")'
|
357
|
+
skipif-ci-and-not-windows = '("CI" in os_environ) and (sys_platform != "windows")'
|
357
358
|
skipif-ci-and-windows = '("CI" in os_environ) and (sys_platform != "windows")'
|
358
359
|
skipif-linux = 'sys_platform == "linux"'
|
359
360
|
skipif-mac = 'sys_platform == "darwin"'
|
@@ -28,6 +28,7 @@ from luigi import Task
|
|
28
28
|
from numpy import inf, int64, isfinite, isinf, isnan, ravel, rint
|
29
29
|
from pathvalidate import validate_filepath
|
30
30
|
from pytest import mark, raises
|
31
|
+
from whenever import Date, DateDelta, PlainDateTime, ZonedDateTime
|
31
32
|
|
32
33
|
from tests.conftest import SKIPIF_CI_AND_WINDOWS
|
33
34
|
from utilities.datetime import (
|
@@ -50,8 +51,10 @@ from utilities.hypothesis import (
|
|
50
51
|
_Draw2InputResolvedToSentinelError,
|
51
52
|
assume_does_not_raise,
|
52
53
|
bool_arrays,
|
54
|
+
date_deltas_whenever,
|
53
55
|
date_durations,
|
54
56
|
dates_two_digit_year,
|
57
|
+
dates_whenever,
|
55
58
|
datetime_durations,
|
56
59
|
draw2,
|
57
60
|
float32s,
|
@@ -73,6 +76,7 @@ from utilities.hypothesis import (
|
|
73
76
|
pairs,
|
74
77
|
paths,
|
75
78
|
plain_datetimes,
|
79
|
+
plain_datetimes_whenever,
|
76
80
|
random_states,
|
77
81
|
sentinels,
|
78
82
|
sets_fixed_length,
|
@@ -94,6 +98,7 @@ from utilities.hypothesis import (
|
|
94
98
|
uint64s,
|
95
99
|
versions,
|
96
100
|
zoned_datetimes,
|
101
|
+
zoned_datetimes_whenever,
|
97
102
|
)
|
98
103
|
from utilities.math import (
|
99
104
|
MAX_FLOAT32,
|
@@ -178,6 +183,31 @@ class TestBoolArrays:
|
|
178
183
|
assert array.shape == shape
|
179
184
|
|
180
185
|
|
186
|
+
class TestDateDeltas:
|
187
|
+
@given(data=data())
|
188
|
+
def test_main(self, *, data: DataObject) -> None:
|
189
|
+
min_value = data.draw(date_deltas_whenever() | none())
|
190
|
+
max_value = data.draw(date_deltas_whenever() | none())
|
191
|
+
with assume_does_not_raise(InvalidArgument):
|
192
|
+
delta = data.draw(
|
193
|
+
date_deltas_whenever(min_value=min_value, max_value=max_value)
|
194
|
+
)
|
195
|
+
assert isinstance(delta, DateDelta)
|
196
|
+
years, months, days = delta.in_years_months_days()
|
197
|
+
assert years == 0
|
198
|
+
assert months == 0
|
199
|
+
if min_value is not None:
|
200
|
+
min_years, min_months, min_days = min_value.in_years_months_days()
|
201
|
+
assert min_years == 0
|
202
|
+
assert min_months == 0
|
203
|
+
assert days >= min_days
|
204
|
+
if max_value is not None:
|
205
|
+
max_years, max_months, max_days = max_value.in_years_months_days()
|
206
|
+
assert max_years == 0
|
207
|
+
assert max_months == 0
|
208
|
+
assert days <= max_days
|
209
|
+
|
210
|
+
|
181
211
|
class TestDateDurations:
|
182
212
|
@given(
|
183
213
|
data=data(),
|
@@ -257,6 +287,20 @@ class TestDatesTwoDigitYear:
|
|
257
287
|
assert date.year == parsed
|
258
288
|
|
259
289
|
|
290
|
+
class TestDatesWhenever:
|
291
|
+
@given(data=data())
|
292
|
+
def test_main(self, *, data: DataObject) -> None:
|
293
|
+
min_value = data.draw(dates_whenever() | none())
|
294
|
+
max_value = data.draw(dates_whenever() | none())
|
295
|
+
with assume_does_not_raise(InvalidArgument):
|
296
|
+
date = data.draw(dates_whenever(min_value=min_value, max_value=max_value))
|
297
|
+
assert isinstance(date, Date)
|
298
|
+
if min_value is not None:
|
299
|
+
assert date >= min_value
|
300
|
+
if max_value is not None:
|
301
|
+
assert date <= max_value
|
302
|
+
|
303
|
+
|
260
304
|
class TestDateTimeDurations:
|
261
305
|
@given(
|
262
306
|
data=data(),
|
@@ -840,6 +884,22 @@ class TestPlainDateTimes:
|
|
840
884
|
_ = data.draw(plain_datetimes(round_="standard"))
|
841
885
|
|
842
886
|
|
887
|
+
class TestPlainDateTimesWhenever:
|
888
|
+
@given(data=data())
|
889
|
+
def test_main(self, *, data: DataObject) -> None:
|
890
|
+
min_value = data.draw(plain_datetimes_whenever() | none())
|
891
|
+
max_value = data.draw(plain_datetimes_whenever() | none())
|
892
|
+
with assume_does_not_raise(InvalidArgument):
|
893
|
+
datetime = data.draw(
|
894
|
+
plain_datetimes_whenever(min_value=min_value, max_value=max_value)
|
895
|
+
)
|
896
|
+
assert isinstance(datetime, PlainDateTime)
|
897
|
+
if min_value is not None:
|
898
|
+
assert datetime >= min_value
|
899
|
+
if max_value is not None:
|
900
|
+
assert datetime <= max_value
|
901
|
+
|
902
|
+
|
843
903
|
class TestRandomStates:
|
844
904
|
@given(data=data())
|
845
905
|
def test_main(self, *, data: DataObject) -> None:
|
@@ -1198,3 +1258,23 @@ class TestZonedDateTimes:
|
|
1198
1258
|
ZonedDateTimesError, match="Rounding requires a timedelta; got None"
|
1199
1259
|
):
|
1200
1260
|
_ = data.draw(zoned_datetimes(round_="standard"))
|
1261
|
+
|
1262
|
+
|
1263
|
+
class TestZonedDateTimesWhenever:
|
1264
|
+
@given(data=data(), time_zone=timezones())
|
1265
|
+
@settings(suppress_health_check={HealthCheck.filter_too_much})
|
1266
|
+
def test_main(self, *, data: DataObject, time_zone: ZoneInfo) -> None:
|
1267
|
+
min_value = data.draw(zoned_datetimes_whenever() | none())
|
1268
|
+
max_value = data.draw(zoned_datetimes_whenever() | none())
|
1269
|
+
with assume_does_not_raise(InvalidArgument):
|
1270
|
+
datetime = data.draw(
|
1271
|
+
zoned_datetimes_whenever(
|
1272
|
+
min_value=min_value, max_value=max_value, time_zone=time_zone
|
1273
|
+
)
|
1274
|
+
)
|
1275
|
+
assert isinstance(datetime, ZonedDateTime)
|
1276
|
+
assert datetime.tz == time_zone.key
|
1277
|
+
if min_value is not None:
|
1278
|
+
assert datetime >= min_value
|
1279
|
+
if max_value is not None:
|
1280
|
+
assert datetime <= max_value
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import datetime as dt
|
4
4
|
from datetime import timezone
|
5
|
-
from logging import DEBUG
|
6
5
|
from re import escape
|
7
6
|
from typing import TYPE_CHECKING
|
8
7
|
from zoneinfo import ZoneInfo
|
@@ -21,7 +20,7 @@ from hypothesis.strategies import (
|
|
21
20
|
timezones,
|
22
21
|
)
|
23
22
|
from pytest import raises
|
24
|
-
from whenever import DateTimeDelta
|
23
|
+
from whenever import DateTimeDelta
|
25
24
|
|
26
25
|
from tests.conftest import SKIPIF_CI_AND_WINDOWS
|
27
26
|
from utilities.datetime import (
|
@@ -61,7 +60,6 @@ from utilities.whenever import (
|
|
61
60
|
SerializePlainDateTimeError,
|
62
61
|
SerializeTimeDeltaError,
|
63
62
|
SerializeZonedDateTimeError,
|
64
|
-
WheneverLogRecord,
|
65
63
|
_CheckValidZonedDateTimeUnequalError,
|
66
64
|
_EnsureTimedeltaNanosecondError,
|
67
65
|
_EnsureTimedeltaParseError,
|
@@ -495,20 +493,3 @@ class TestToDateTimeDelta:
|
|
495
493
|
_ToDateTimeDeltaError, match="Unable to create DateTimeDelta; got .*"
|
496
494
|
):
|
497
495
|
_ = _to_datetime_delta(timedelta)
|
498
|
-
|
499
|
-
|
500
|
-
class TestWheneverLogRecord:
|
501
|
-
def test_init(self) -> None:
|
502
|
-
_ = WheneverLogRecord("name", DEBUG, "pathname", 0, None, None, None)
|
503
|
-
|
504
|
-
def test_get_length(self) -> None:
|
505
|
-
assert isinstance(WheneverLogRecord._get_length(), int)
|
506
|
-
|
507
|
-
def test_get_now(self) -> None:
|
508
|
-
assert isinstance(WheneverLogRecord._get_now(), ZonedDateTime)
|
509
|
-
|
510
|
-
def test_get_time_zone(self) -> None:
|
511
|
-
assert isinstance(WheneverLogRecord._get_time_zone(), ZoneInfo)
|
512
|
-
|
513
|
-
def test_get_time_zone_key(self) -> None:
|
514
|
-
assert isinstance(WheneverLogRecord._get_time_zone_key(), str)
|
@@ -0,0 +1,194 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from logging import DEBUG
|
4
|
+
from zoneinfo import ZoneInfo
|
5
|
+
|
6
|
+
from hypothesis import given
|
7
|
+
from hypothesis.strategies import just, timezones
|
8
|
+
from pytest import mark, param, raises
|
9
|
+
from whenever import DateDelta, DateTimeDelta, TimeDelta, ZonedDateTime
|
10
|
+
|
11
|
+
from tests.conftest import IS_CI
|
12
|
+
from utilities.hypothesis import zoned_datetimes_whenever
|
13
|
+
from utilities.tzdata import HongKong, Tokyo
|
14
|
+
from utilities.whenever2 import (
|
15
|
+
DATE_DELTA_MAX,
|
16
|
+
DATE_DELTA_MIN,
|
17
|
+
DATE_MAX,
|
18
|
+
DATE_MIN,
|
19
|
+
DATE_TIME_DELTA_MAX,
|
20
|
+
DATE_TIME_DELTA_MIN,
|
21
|
+
NOW_UTC,
|
22
|
+
PLAIN_DATE_TIME_MAX,
|
23
|
+
PLAIN_DATE_TIME_MIN,
|
24
|
+
TIME_DELTA_MAX,
|
25
|
+
TIME_DELTA_MIN,
|
26
|
+
ZONED_DATE_TIME_MAX,
|
27
|
+
ZONED_DATE_TIME_MIN,
|
28
|
+
WheneverLogRecord,
|
29
|
+
from_timestamp,
|
30
|
+
from_timestamp_millis,
|
31
|
+
from_timestamp_nanos,
|
32
|
+
get_now,
|
33
|
+
get_now_local,
|
34
|
+
)
|
35
|
+
from utilities.zoneinfo import UTC
|
36
|
+
|
37
|
+
|
38
|
+
class TestFromTimeStamp:
|
39
|
+
@given(datetime=zoned_datetimes_whenever(time_zone=UTC if IS_CI else timezones()))
|
40
|
+
def test_main(self, *, datetime: ZonedDateTime) -> None:
|
41
|
+
datetime = datetime.round("second")
|
42
|
+
timestamp = datetime.to_tz(UTC.key).timestamp()
|
43
|
+
result = from_timestamp(timestamp, time_zone=ZoneInfo(datetime.tz))
|
44
|
+
assert result == datetime
|
45
|
+
|
46
|
+
@given(datetime=zoned_datetimes_whenever(time_zone=UTC if IS_CI else timezones()))
|
47
|
+
def test_millis(self, *, datetime: ZonedDateTime) -> None:
|
48
|
+
datetime = datetime.round("millisecond")
|
49
|
+
timestamp = datetime.to_tz(UTC.key).timestamp_millis()
|
50
|
+
result = from_timestamp_millis(timestamp, time_zone=ZoneInfo(datetime.tz))
|
51
|
+
assert result == datetime
|
52
|
+
|
53
|
+
@given(datetime=zoned_datetimes_whenever(time_zone=UTC if IS_CI else timezones()))
|
54
|
+
def test_nanos(self, *, datetime: ZonedDateTime) -> None:
|
55
|
+
timestamp = datetime.to_tz(UTC.key).timestamp_nanos()
|
56
|
+
result = from_timestamp_nanos(timestamp, time_zone=ZoneInfo(datetime.tz))
|
57
|
+
assert result == datetime
|
58
|
+
|
59
|
+
|
60
|
+
class TestGetNow:
|
61
|
+
@given(time_zone=just(UTC) if IS_CI else timezones())
|
62
|
+
def test_function(self, *, time_zone: ZoneInfo) -> None:
|
63
|
+
now = get_now(time_zone=time_zone)
|
64
|
+
assert isinstance(now, ZonedDateTime)
|
65
|
+
assert now.tz == time_zone.key
|
66
|
+
|
67
|
+
def test_constant(self) -> None:
|
68
|
+
assert isinstance(NOW_UTC, ZonedDateTime)
|
69
|
+
assert NOW_UTC.tz == "UTC"
|
70
|
+
|
71
|
+
|
72
|
+
class TestGetNowLocal:
|
73
|
+
def test_function(self) -> None:
|
74
|
+
now = get_now_local()
|
75
|
+
assert isinstance(now, ZonedDateTime)
|
76
|
+
ETC = ZoneInfo("Etc/UTC") # noqa: N806
|
77
|
+
time_zones = {ETC, HongKong, Tokyo, UTC}
|
78
|
+
assert any(now.tz == time_zone.key for time_zone in time_zones)
|
79
|
+
|
80
|
+
|
81
|
+
class TestMinMax:
|
82
|
+
def test_date_min(self) -> None:
|
83
|
+
with raises(ValueError, match="Resulting date out of range"):
|
84
|
+
_ = DATE_MIN - DateDelta(days=1)
|
85
|
+
|
86
|
+
def test_date_max(self) -> None:
|
87
|
+
with raises(ValueError, match="Resulting date out of range"):
|
88
|
+
_ = DATE_MAX + DateDelta(days=1)
|
89
|
+
|
90
|
+
def test_date_delta_min(self) -> None:
|
91
|
+
with raises(ValueError, match="Addition result out of bounds"):
|
92
|
+
_ = DATE_DELTA_MIN - DateDelta(days=1)
|
93
|
+
|
94
|
+
def test_date_delta_max(self) -> None:
|
95
|
+
with raises(ValueError, match="Addition result out of bounds"):
|
96
|
+
_ = DATE_DELTA_MAX + DateDelta(days=1)
|
97
|
+
|
98
|
+
@mark.parametrize(
|
99
|
+
"delta",
|
100
|
+
[
|
101
|
+
param(DateTimeDelta(days=1)),
|
102
|
+
param(DateTimeDelta(seconds=1)),
|
103
|
+
param(DateTimeDelta(milliseconds=1)),
|
104
|
+
param(DateTimeDelta(microseconds=1)),
|
105
|
+
param(DateTimeDelta(nanoseconds=1)),
|
106
|
+
],
|
107
|
+
)
|
108
|
+
def test_date_time_delta_min(self, *, delta: DateTimeDelta) -> None:
|
109
|
+
with raises(ValueError, match="Addition result out of bounds"):
|
110
|
+
_ = DATE_TIME_DELTA_MIN - delta
|
111
|
+
|
112
|
+
@mark.parametrize(
|
113
|
+
("delta", "is_ok"),
|
114
|
+
[
|
115
|
+
param(DateTimeDelta(days=1), False),
|
116
|
+
param(DateTimeDelta(seconds=1), False),
|
117
|
+
param(DateTimeDelta(milliseconds=999), True),
|
118
|
+
param(DateTimeDelta(milliseconds=1000), False),
|
119
|
+
param(DateTimeDelta(microseconds=999_999), True),
|
120
|
+
param(DateTimeDelta(microseconds=1_000_000), False),
|
121
|
+
param(DateTimeDelta(nanoseconds=999_999_999), True),
|
122
|
+
param(DateTimeDelta(nanoseconds=1_000_000_000), False),
|
123
|
+
],
|
124
|
+
)
|
125
|
+
def test_date_time_delta_max(self, *, delta: DateTimeDelta, is_ok: bool) -> None:
|
126
|
+
if is_ok:
|
127
|
+
_ = DATE_TIME_DELTA_MAX + delta
|
128
|
+
else:
|
129
|
+
with raises(ValueError, match="Addition result out of bounds"):
|
130
|
+
_ = DATE_TIME_DELTA_MAX + delta
|
131
|
+
|
132
|
+
def test_plain_date_time_min(self) -> None:
|
133
|
+
with raises(ValueError, match=r"Result of subtract\(\) out of range"):
|
134
|
+
_ = PLAIN_DATE_TIME_MIN.subtract(nanoseconds=1, ignore_dst=True)
|
135
|
+
|
136
|
+
def test_plain_date_time_max(self) -> None:
|
137
|
+
_ = PLAIN_DATE_TIME_MAX.add(nanoseconds=999, ignore_dst=True)
|
138
|
+
with raises(ValueError, match=r"Result of add\(\) out of range"):
|
139
|
+
_ = PLAIN_DATE_TIME_MAX.add(microseconds=1, ignore_dst=True)
|
140
|
+
|
141
|
+
@mark.parametrize(
|
142
|
+
"delta",
|
143
|
+
[
|
144
|
+
param(TimeDelta(seconds=1)),
|
145
|
+
param(TimeDelta(milliseconds=1)),
|
146
|
+
param(TimeDelta(microseconds=1)),
|
147
|
+
param(TimeDelta(nanoseconds=1)),
|
148
|
+
],
|
149
|
+
)
|
150
|
+
def test_time_delta_min(self, *, delta: TimeDelta) -> None:
|
151
|
+
with raises(ValueError, match="Addition result out of range"):
|
152
|
+
_ = TIME_DELTA_MIN - delta
|
153
|
+
|
154
|
+
@mark.parametrize(
|
155
|
+
("delta", "is_ok"),
|
156
|
+
[
|
157
|
+
param(TimeDelta(seconds=1), False),
|
158
|
+
param(TimeDelta(milliseconds=999), True),
|
159
|
+
param(TimeDelta(milliseconds=1000), False),
|
160
|
+
param(TimeDelta(microseconds=999_999), True),
|
161
|
+
param(TimeDelta(microseconds=1_000_000), False),
|
162
|
+
param(TimeDelta(nanoseconds=999_999_999), True),
|
163
|
+
param(TimeDelta(nanoseconds=1_000_000_000), False),
|
164
|
+
],
|
165
|
+
)
|
166
|
+
def test_time_delta_max(self, *, delta: TimeDelta, is_ok: bool) -> None:
|
167
|
+
if is_ok:
|
168
|
+
_ = TIME_DELTA_MAX + delta
|
169
|
+
else:
|
170
|
+
with raises(ValueError, match="Addition result out of range"):
|
171
|
+
_ = TIME_DELTA_MAX + delta
|
172
|
+
|
173
|
+
def test_zoned_date_time_min(self) -> None:
|
174
|
+
with raises(ValueError, match="Instant is out of range"):
|
175
|
+
_ = ZONED_DATE_TIME_MIN.subtract(nanoseconds=1)
|
176
|
+
|
177
|
+
def test_zoned_date_time_max(self) -> None:
|
178
|
+
_ = ZONED_DATE_TIME_MAX.add(nanoseconds=999)
|
179
|
+
with raises(ValueError, match="Instant is out of range"):
|
180
|
+
_ = ZONED_DATE_TIME_MAX.add(microseconds=1)
|
181
|
+
|
182
|
+
|
183
|
+
class TestWheneverLogRecord:
|
184
|
+
def test_init(self) -> None:
|
185
|
+
_ = WheneverLogRecord("name", DEBUG, "pathname", 0, None, None, None)
|
186
|
+
|
187
|
+
def test_get_length(self) -> None:
|
188
|
+
assert isinstance(WheneverLogRecord._get_length(), int)
|
189
|
+
|
190
|
+
def test_get_time_zone(self) -> None:
|
191
|
+
assert isinstance(WheneverLogRecord._get_time_zone(), ZoneInfo)
|
192
|
+
|
193
|
+
def test_get_time_zone_key(self) -> None:
|
194
|
+
assert isinstance(WheneverLogRecord._get_time_zone_key(), str)
|
@@ -47,6 +47,7 @@ from hypothesis.strategies import (
|
|
47
47
|
uuids,
|
48
48
|
)
|
49
49
|
from hypothesis.utils.conventions import not_set
|
50
|
+
from whenever import Date, DateDelta
|
50
51
|
|
51
52
|
from utilities.datetime import (
|
52
53
|
DATETIME_MAX_NAIVE,
|
@@ -88,7 +89,7 @@ from utilities.platform import IS_WINDOWS
|
|
88
89
|
from utilities.sentinel import Sentinel, sentinel
|
89
90
|
from utilities.tempfile import TEMP_DIR, TemporaryDirectory
|
90
91
|
from utilities.version import Version
|
91
|
-
from utilities.zoneinfo import UTC
|
92
|
+
from utilities.zoneinfo import UTC, ensure_time_zone
|
92
93
|
|
93
94
|
if TYPE_CHECKING:
|
94
95
|
from collections.abc import Collection, Hashable, Iterable, Iterator, Sequence
|
@@ -96,9 +97,10 @@ if TYPE_CHECKING:
|
|
96
97
|
|
97
98
|
from hypothesis.database import ExampleDatabase
|
98
99
|
from numpy.random import RandomState
|
100
|
+
from whenever import PlainDateTime, ZonedDateTime
|
99
101
|
|
100
102
|
from utilities.numpy import NDArrayB, NDArrayF, NDArrayI, NDArrayO
|
101
|
-
from utilities.types import Duration, Number, RoundMode
|
103
|
+
from utilities.types import Duration, Number, RoundMode, TimeZoneLike
|
102
104
|
|
103
105
|
|
104
106
|
_T = TypeVar("_T")
|
@@ -158,6 +160,45 @@ def bool_arrays(
|
|
158
160
|
##
|
159
161
|
|
160
162
|
|
163
|
+
@composite
|
164
|
+
def date_deltas_whenever(
|
165
|
+
draw: DrawFn,
|
166
|
+
/,
|
167
|
+
*,
|
168
|
+
min_value: MaybeSearchStrategy[DateDelta | None] = None,
|
169
|
+
max_value: MaybeSearchStrategy[DateDelta | None] = None,
|
170
|
+
) -> DateDelta:
|
171
|
+
"""Strategy for generating date deltas."""
|
172
|
+
from utilities.whenever2 import DATE_DELTA_MAX, DATE_DELTA_MIN
|
173
|
+
|
174
|
+
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
175
|
+
match min_value_:
|
176
|
+
case None:
|
177
|
+
min_value_ = DATE_DELTA_MIN
|
178
|
+
case DateDelta():
|
179
|
+
...
|
180
|
+
case _ as never:
|
181
|
+
assert_never(never)
|
182
|
+
match max_value_:
|
183
|
+
case None:
|
184
|
+
max_value_ = DATE_DELTA_MAX
|
185
|
+
case DateDelta():
|
186
|
+
...
|
187
|
+
case _ as never:
|
188
|
+
assert_never(never)
|
189
|
+
min_years, min_months, min_days = min_value_.in_years_months_days()
|
190
|
+
assert min_years == 0
|
191
|
+
assert min_months == 0
|
192
|
+
max_years, max_months, max_days = max_value_.in_years_months_days()
|
193
|
+
assert max_years == 0
|
194
|
+
assert max_months == 0
|
195
|
+
days = draw(integers(min_value=min_days, max_value=max_days))
|
196
|
+
return DateDelta(days=days)
|
197
|
+
|
198
|
+
|
199
|
+
##
|
200
|
+
|
201
|
+
|
161
202
|
@composite
|
162
203
|
def date_durations(
|
163
204
|
draw: DrawFn,
|
@@ -238,6 +279,41 @@ def dates_two_digit_year(
|
|
238
279
|
##
|
239
280
|
|
240
281
|
|
282
|
+
@composite
|
283
|
+
def dates_whenever(
|
284
|
+
draw: DrawFn,
|
285
|
+
/,
|
286
|
+
*,
|
287
|
+
min_value: MaybeSearchStrategy[Date | None] = None,
|
288
|
+
max_value: MaybeSearchStrategy[Date | None] = None,
|
289
|
+
) -> Date:
|
290
|
+
"""Strategy for generating dates."""
|
291
|
+
from utilities.whenever2 import DATE_MAX, DATE_MIN
|
292
|
+
|
293
|
+
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
294
|
+
match min_value_:
|
295
|
+
case None:
|
296
|
+
min_value_ = DATE_MIN
|
297
|
+
case Date():
|
298
|
+
...
|
299
|
+
case _ as never:
|
300
|
+
assert_never(never)
|
301
|
+
match max_value_:
|
302
|
+
case None:
|
303
|
+
max_value_ = DATE_MAX
|
304
|
+
case Date():
|
305
|
+
...
|
306
|
+
case _ as never:
|
307
|
+
assert_never(never)
|
308
|
+
py_date = draw(
|
309
|
+
dates(min_value=min_value_.py_date(), max_value=max_value_.py_date())
|
310
|
+
)
|
311
|
+
return Date.from_py_date(py_date)
|
312
|
+
|
313
|
+
|
314
|
+
##
|
315
|
+
|
316
|
+
|
241
317
|
@composite
|
242
318
|
def datetime_durations(
|
243
319
|
draw: DrawFn,
|
@@ -920,7 +996,7 @@ def _pairs_map(elements: list[_T], /) -> tuple[_T, _T]:
|
|
920
996
|
|
921
997
|
def paths() -> SearchStrategy[Path]:
|
922
998
|
"""Strategy for generating `Path`s."""
|
923
|
-
reserved = {"NUL"}
|
999
|
+
reserved = {"AUX", "NUL"}
|
924
1000
|
strategy = text_ascii(min_size=1, max_size=10).filter(lambda x: x not in reserved)
|
925
1001
|
return lists(strategy, max_size=10).map(lambda parts: Path(*parts))
|
926
1002
|
|
@@ -965,6 +1041,45 @@ class PlainDateTimesError(Exception):
|
|
965
1041
|
##
|
966
1042
|
|
967
1043
|
|
1044
|
+
@composite
|
1045
|
+
def plain_datetimes_whenever(
|
1046
|
+
draw: DrawFn,
|
1047
|
+
/,
|
1048
|
+
*,
|
1049
|
+
min_value: MaybeSearchStrategy[PlainDateTime | None] = None,
|
1050
|
+
max_value: MaybeSearchStrategy[PlainDateTime | None] = None,
|
1051
|
+
) -> PlainDateTime:
|
1052
|
+
"""Strategy for generating plain datetimes."""
|
1053
|
+
from whenever import PlainDateTime
|
1054
|
+
|
1055
|
+
from utilities.whenever2 import PLAIN_DATE_TIME_MAX, PLAIN_DATE_TIME_MIN
|
1056
|
+
|
1057
|
+
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
1058
|
+
match min_value_:
|
1059
|
+
case None:
|
1060
|
+
min_value_ = PLAIN_DATE_TIME_MIN
|
1061
|
+
case PlainDateTime():
|
1062
|
+
...
|
1063
|
+
case _ as never:
|
1064
|
+
assert_never(never)
|
1065
|
+
match max_value_:
|
1066
|
+
case None:
|
1067
|
+
max_value_ = PLAIN_DATE_TIME_MAX
|
1068
|
+
case PlainDateTime():
|
1069
|
+
...
|
1070
|
+
case _ as never:
|
1071
|
+
assert_never(never)
|
1072
|
+
py_datetime = draw(
|
1073
|
+
datetimes(
|
1074
|
+
min_value=min_value_.py_datetime(), max_value=max_value_.py_datetime()
|
1075
|
+
)
|
1076
|
+
)
|
1077
|
+
return PlainDateTime.from_py_datetime(py_datetime)
|
1078
|
+
|
1079
|
+
|
1080
|
+
##
|
1081
|
+
|
1082
|
+
|
968
1083
|
@composite
|
969
1084
|
def random_states(
|
970
1085
|
draw: DrawFn, /, *, seed: MaybeSearchStrategy[int | None] = None
|
@@ -1427,6 +1542,46 @@ class ZonedDateTimesError(Exception):
|
|
1427
1542
|
return "Rounding requires a timedelta; got None"
|
1428
1543
|
|
1429
1544
|
|
1545
|
+
##
|
1546
|
+
|
1547
|
+
|
1548
|
+
@composite
|
1549
|
+
def zoned_datetimes_whenever(
|
1550
|
+
draw: DrawFn,
|
1551
|
+
/,
|
1552
|
+
*,
|
1553
|
+
min_value: MaybeSearchStrategy[PlainDateTime | ZonedDateTime | None] = None,
|
1554
|
+
max_value: MaybeSearchStrategy[PlainDateTime | ZonedDateTime | None] = None,
|
1555
|
+
time_zone: MaybeSearchStrategy[TimeZoneLike] = UTC,
|
1556
|
+
) -> ZonedDateTime:
|
1557
|
+
"""Strategy for generating zoned datetimes."""
|
1558
|
+
from whenever import PlainDateTime, ZonedDateTime
|
1559
|
+
|
1560
|
+
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
1561
|
+
time_zone_ = ensure_time_zone(draw2(draw, time_zone))
|
1562
|
+
match min_value_:
|
1563
|
+
case None | PlainDateTime():
|
1564
|
+
...
|
1565
|
+
case ZonedDateTime():
|
1566
|
+
with assume_does_not_raise(ValueError):
|
1567
|
+
min_value_ = min_value_.to_tz(time_zone_.key).to_plain()
|
1568
|
+
case _ as never:
|
1569
|
+
assert_never(never)
|
1570
|
+
match max_value_:
|
1571
|
+
case None | PlainDateTime():
|
1572
|
+
...
|
1573
|
+
case ZonedDateTime():
|
1574
|
+
with assume_does_not_raise(ValueError):
|
1575
|
+
max_value_ = max_value_.to_tz(time_zone_.key).to_plain()
|
1576
|
+
case _ as never:
|
1577
|
+
assert_never(never)
|
1578
|
+
plain_datetime = draw(
|
1579
|
+
plain_datetimes_whenever(min_value=min_value_, max_value=max_value_)
|
1580
|
+
)
|
1581
|
+
with assume_does_not_raise(ValueError):
|
1582
|
+
return plain_datetime.assume_tz(time_zone_.key, disambiguate="raise")
|
1583
|
+
|
1584
|
+
|
1430
1585
|
__all__ = [
|
1431
1586
|
"Draw2Error",
|
1432
1587
|
"MaybeSearchStrategy",
|
@@ -1435,8 +1590,10 @@ __all__ = [
|
|
1435
1590
|
"ZonedDateTimesError",
|
1436
1591
|
"assume_does_not_raise",
|
1437
1592
|
"bool_arrays",
|
1593
|
+
"date_deltas_whenever",
|
1438
1594
|
"date_durations",
|
1439
1595
|
"dates_two_digit_year",
|
1596
|
+
"dates_whenever",
|
1440
1597
|
"datetime_durations",
|
1441
1598
|
"draw2",
|
1442
1599
|
"float32s",
|
@@ -1460,6 +1617,7 @@ __all__ = [
|
|
1460
1617
|
"paths",
|
1461
1618
|
"plain_datetimes",
|
1462
1619
|
"plain_datetimes",
|
1620
|
+
"plain_datetimes_whenever",
|
1463
1621
|
"random_states",
|
1464
1622
|
"sentinels",
|
1465
1623
|
"sets_fixed_length",
|
@@ -1480,4 +1638,5 @@ __all__ = [
|
|
1480
1638
|
"uint64s",
|
1481
1639
|
"versions",
|
1482
1640
|
"zoned_datetimes",
|
1641
|
+
"zoned_datetimes_whenever",
|
1483
1642
|
]
|
@@ -190,7 +190,7 @@ def get_formatter(
|
|
190
190
|
) -> Formatter:
|
191
191
|
"""Get the formatter; colored if available."""
|
192
192
|
if whenever:
|
193
|
-
from utilities.
|
193
|
+
from utilities.whenever2 import WheneverLogRecord
|
194
194
|
|
195
195
|
setLogRecordFactory(WheneverLogRecord)
|
196
196
|
format_ = format_.replace("{asctime}", "{zoned_datetime}")
|
@@ -234,7 +234,7 @@ def is_instance_gen(obj: Any, type_: Any, /) -> bool:
|
|
234
234
|
"""Check if an instance relationship holds, except bool<int."""
|
235
235
|
# parent
|
236
236
|
if isinstance(type_, tuple):
|
237
|
-
return any(is_instance_gen(obj, t) for t in type_)
|
237
|
+
return any(is_instance_gen(obj, t) for t in type_) # skipif-ci-and-not-windows
|
238
238
|
if is_literal_type(type_):
|
239
239
|
return obj in get_args(type_)
|
240
240
|
if is_union_type(type_):
|