dycw-utilities 0.131.0__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.0 → dycw_utilities-0.131.2}/PKG-INFO +1 -1
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/pyproject.toml +4 -2
- dycw_utilities-0.131.2/src/tests/conftest.py +425 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_hypothesis.py +80 -39
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_sqlalchemy.py +283 -258
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_sqlalchemy_polars.py +125 -98
- {dycw_utilities-0.131.0 → 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.0 → dycw_utilities-0.131.2}/src/utilities/__init__.py +1 -1
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/hypothesis.py +162 -51
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/logging.py +1 -1
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/sqlalchemy_polars.py +1 -17
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/typing.py +1 -1
- {dycw_utilities-0.131.0 → 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.0/src/tests/conftest.py +0 -27
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/.gitignore +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/LICENSE +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/README.md +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/__init__.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/__init__.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_missing/__init__.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_missing/module.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_with/__init__.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_with/outer_1.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_with/outer_2.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_without/__init__.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_without/module_1.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/package_without/module_2.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/standalone.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/modules/with_imports.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_aiolimiter.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_altair.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_asyncio.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_asyncio_classes/__init__.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_asyncio_classes/loopers.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_asyncio_classes/redis.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_atomicwrites.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_atools.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_cachetools.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_click.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_concurrent.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_contextlib.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_contextvars.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_cryptography.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_cvxpy.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_dataclasses.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_datetime.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_enum.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_errors.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_eventkit.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_fastapi.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_fpdf2.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_functions.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_functools.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_getpass.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_git.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_hashlib.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_http.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_importlib.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_inflect.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_ipython.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_iterables.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_jupyter.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_libcst.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_lightweight_charts.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_logging.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_luigi.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_math.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_memory_profiler.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_modules.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_more_itertools.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_numpy.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_operator.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_optuna.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_orjson.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_os.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_parse.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_pathlib.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_period.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_pickle.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_platform.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_polars.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_polars_ols.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_pottery.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_pqdm.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_psutil.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_pydantic.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_pyinstrument.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_pyrsistent.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_pytest.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_pytest_regressions.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_python_dotenv.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_random.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_re.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_redis.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_reprlib.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_scipy.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_sentinel.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_shelve.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_slack_sdk.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_socket.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_statsmodel.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_streamlit.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_string.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_tempfile.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_tenacity.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_text.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_threading.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_timer.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_traceback.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_types.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_typing.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_typing_funcs/__init__.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_typing_funcs/no_future.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_typing_funcs/with_future.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_tzdata.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_tzlocal.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_uuid.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_version.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_warnings.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_zipfile.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/tests/test_zoneinfo.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/aiolimiter.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/altair.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/asyncio.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/atomicwrites.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/atools.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/cachetools.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/click.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/concurrent.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/contextlib.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/contextvars.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/cryptography.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/cvxpy.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/dataclasses.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/datetime.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/enum.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/errors.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/eventkit.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/fastapi.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/fpdf2.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/functions.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/functools.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/getpass.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/git.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/hashlib.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/http.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/importlib.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/inflect.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/ipython.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/iterables.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/jupyter.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/libcst.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/lightweight_charts.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/luigi.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/math.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/memory_profiler.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/modules.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/more_itertools.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/numpy.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/operator.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/optuna.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/orjson.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/os.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/parse.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/pathlib.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/period.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/pickle.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/platform.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/polars.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/polars_ols.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/pottery.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/pqdm.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/psutil.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/py.typed +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/pydantic.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/pyinstrument.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/pyrsistent.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/pytest.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/pytest_regressions.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/python_dotenv.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/random.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/re.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/redis.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/reprlib.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/scipy.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/sentinel.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/shelve.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/slack_sdk.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/socket.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/sqlalchemy.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/statsmodels.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/streamlit.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/string.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/tempfile.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/tenacity.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/text.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/threading.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/timer.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/traceback.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/types.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/tzdata.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/tzlocal.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/uuid.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/version.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/warnings.py +0 -0
- {dycw_utilities-0.131.0 → dycw_utilities-0.131.2}/src/utilities/zipfile.py +0 -0
- {dycw_utilities-0.131.0 → 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"'
|
@@ -460,6 +461,7 @@ filterwarnings = [
|
|
460
461
|
"ignore:unclosed <StreamWriter .*>:ResourceWarning", # redis
|
461
462
|
"ignore:unclosed <socket.*socket .*>:ResourceWarning", # redis
|
462
463
|
"ignore:unclosed Connection <redis.*asyncio.*connection.*Connection.*>:ResourceWarning", # redis
|
464
|
+
"ignore:unclosed connection <asyncpg.*connection.*Connection.*>:ResourceWarning", # asyncpg
|
463
465
|
"ignore:unclosed event loop <_UnixSelectorEventLoop .*>:ResourceWarning", # redis
|
464
466
|
"ignore:unclosed file <_io.*TextIOWrapper .*>:ResourceWarning", # logging
|
465
467
|
"ignore:unclosed transport <_SelectorSocketTransport .*>:ResourceWarning", # redis
|
@@ -0,0 +1,425 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import re
|
4
|
+
from asyncio import sleep
|
5
|
+
from contextlib import suppress
|
6
|
+
from os import environ
|
7
|
+
from re import MULTILINE, Pattern
|
8
|
+
from typing import TYPE_CHECKING, Any
|
9
|
+
|
10
|
+
from pytest import fixture, mark, param
|
11
|
+
from sqlalchemy import text
|
12
|
+
|
13
|
+
from utilities.datetime import MINUTE, get_now, parse_datetime_compact
|
14
|
+
from utilities.platform import IS_NOT_LINUX, IS_WINDOWS
|
15
|
+
from utilities.re import ExtractGroupError, extract_group
|
16
|
+
from utilities.text import strip_and_dedent
|
17
|
+
|
18
|
+
if TYPE_CHECKING:
|
19
|
+
from collections.abc import Sequence
|
20
|
+
from pathlib import Path
|
21
|
+
|
22
|
+
from _pytest.fixtures import SubRequest
|
23
|
+
|
24
|
+
|
25
|
+
FLAKY = mark.flaky(reruns=5, reruns_delay=1)
|
26
|
+
IS_CI = "CI" in environ
|
27
|
+
SKIPIF_CI = mark.skipif(IS_CI, reason="Skipped for CI")
|
28
|
+
IS_CI_AND_WINDOWS = IS_CI and IS_WINDOWS
|
29
|
+
SKIPIF_CI_AND_WINDOWS = mark.skipif(IS_CI_AND_WINDOWS, reason="Skipped for CI/Windows")
|
30
|
+
SKIPIF_CI_AND_NOT_LINUX = mark.skipif(
|
31
|
+
IS_CI and IS_NOT_LINUX, reason="Skipped for CI/non-Linux"
|
32
|
+
)
|
33
|
+
|
34
|
+
|
35
|
+
# hypothesis
|
36
|
+
|
37
|
+
|
38
|
+
try:
|
39
|
+
from utilities.hypothesis import setup_hypothesis_profiles
|
40
|
+
except ModuleNotFoundError:
|
41
|
+
pass
|
42
|
+
else:
|
43
|
+
setup_hypothesis_profiles()
|
44
|
+
|
45
|
+
|
46
|
+
# fixtures - sqlalchemy
|
47
|
+
|
48
|
+
|
49
|
+
@fixture(params=[param("sqlite"), param("postgresql", marks=SKIPIF_CI)])
|
50
|
+
async def test_engine(*, request: SubRequest, tmp_path: Path) -> Any:
|
51
|
+
from utilities.sqlalchemy import create_async_engine
|
52
|
+
|
53
|
+
dialect = request.param
|
54
|
+
match dialect:
|
55
|
+
case "sqlite":
|
56
|
+
db_path = tmp_path / "db.sqlite"
|
57
|
+
return create_async_engine("sqlite+aiosqlite", database=str(db_path))
|
58
|
+
case "postgresql":
|
59
|
+
engine = create_async_engine(
|
60
|
+
"postgresql+asyncpg", host="localhost", port=5432, database="testing"
|
61
|
+
)
|
62
|
+
query = text("SELECT tablename FROM pg_tables")
|
63
|
+
async with engine.begin() as conn:
|
64
|
+
tables: Sequence[str] = (await conn.execute(query)).scalars().all()
|
65
|
+
for table in tables:
|
66
|
+
if _is_to_drop(table):
|
67
|
+
async with engine.begin() as conn:
|
68
|
+
with suppress(Exception):
|
69
|
+
_ = await conn.execute(
|
70
|
+
text(f'DROP TABLE IF EXISTS "{table}" CASCADE')
|
71
|
+
)
|
72
|
+
await sleep(0.01)
|
73
|
+
return engine
|
74
|
+
case _:
|
75
|
+
msg = f"Unsupported dialect: {dialect}"
|
76
|
+
raise NotImplementedError(msg)
|
77
|
+
|
78
|
+
|
79
|
+
def _is_to_drop(table: str, /) -> bool:
|
80
|
+
try:
|
81
|
+
datetime_str = extract_group(r"^(\d{8}T\d{6})_", table)
|
82
|
+
except ExtractGroupError:
|
83
|
+
return True
|
84
|
+
datetime = parse_datetime_compact(datetime_str)
|
85
|
+
now = get_now()
|
86
|
+
return (now - datetime) >= MINUTE
|
87
|
+
|
88
|
+
|
89
|
+
# fixtures - traceback
|
90
|
+
|
91
|
+
|
92
|
+
@fixture
|
93
|
+
def traceback_func_chain() -> Pattern[str]:
|
94
|
+
return re.compile(
|
95
|
+
strip_and_dedent(
|
96
|
+
r"""
|
97
|
+
Date/time \| .+
|
98
|
+
Started \| .+
|
99
|
+
Duration \| .+
|
100
|
+
User \| .+
|
101
|
+
Host \| .+
|
102
|
+
Version \|\s
|
103
|
+
|
104
|
+
Exception chain 1/2:
|
105
|
+
Frame 1/1: func_chain_first \(tests\.test_traceback_funcs\.chain\)
|
106
|
+
Inputs:
|
107
|
+
args\[0\] = 1
|
108
|
+
args\[1\] = 2
|
109
|
+
args\[2\] = 3
|
110
|
+
args\[3\] = 4
|
111
|
+
kwargs\[c\] = 5
|
112
|
+
kwargs\[d\] = 6
|
113
|
+
kwargs\[e\] = 7
|
114
|
+
Locals:
|
115
|
+
a = 2
|
116
|
+
b = 4
|
117
|
+
c = 10
|
118
|
+
args = \(6, 8\)
|
119
|
+
kwargs = {'d': 12, 'e': 14}
|
120
|
+
msg = 'Assertion failed: Result \(112\) must be divisible by 10'
|
121
|
+
Line 19:
|
122
|
+
raise ValueError\(msg\) from error
|
123
|
+
Raised:
|
124
|
+
builtins\.ValueError\(Assertion failed: Result \(112\) must be divisible by 10\)
|
125
|
+
|
126
|
+
Exception chain 2/2:
|
127
|
+
Frame 1/1: func_chain_second \(tests\.test_traceback_funcs\.chain\)
|
128
|
+
Inputs:
|
129
|
+
args\[0\] = 2
|
130
|
+
args\[1\] = 4
|
131
|
+
args\[2\] = 6
|
132
|
+
args\[3\] = 8
|
133
|
+
kwargs\[c\] = 10
|
134
|
+
kwargs\[d\] = 12
|
135
|
+
kwargs\[e\] = 14
|
136
|
+
Locals:
|
137
|
+
a = 4
|
138
|
+
b = 8
|
139
|
+
c = 20
|
140
|
+
args = \(12, 16\)
|
141
|
+
kwargs = {'d': 24, 'e': 28}
|
142
|
+
result = 112
|
143
|
+
Line 30:
|
144
|
+
assert result % 10 == 0, f"Result \({result}\) must be divisible by 10"
|
145
|
+
Raised:
|
146
|
+
builtins\.AssertionError\(Result \(112\) must be divisible by 10\)
|
147
|
+
"""
|
148
|
+
),
|
149
|
+
flags=MULTILINE,
|
150
|
+
)
|
151
|
+
|
152
|
+
|
153
|
+
@fixture
|
154
|
+
def traceback_func_one() -> Pattern[str]:
|
155
|
+
return re.compile(
|
156
|
+
strip_and_dedent(
|
157
|
+
r"""
|
158
|
+
Date/time \| .+
|
159
|
+
Started \| .+
|
160
|
+
Duration \| .+
|
161
|
+
User \| .+
|
162
|
+
Host \| .+
|
163
|
+
Version \|\s
|
164
|
+
|
165
|
+
Frame 1/1: func_one \(tests\.test_traceback_funcs\.one\)
|
166
|
+
Inputs:
|
167
|
+
args\[0\] = 1
|
168
|
+
args\[1\] = 2
|
169
|
+
args\[2\] = 3
|
170
|
+
args\[3\] = 4
|
171
|
+
kwargs\[c\] = 5
|
172
|
+
kwargs\[d\] = 6
|
173
|
+
kwargs\[e\] = 7
|
174
|
+
Locals:
|
175
|
+
a = 2
|
176
|
+
b = 4
|
177
|
+
c = 10
|
178
|
+
args = \(6, 8\)
|
179
|
+
kwargs = {'d': 12, 'e': 14}
|
180
|
+
result = 56
|
181
|
+
Line 16:
|
182
|
+
assert result % 10 == 0, f"Result \({result}\) must be divisible by 10"
|
183
|
+
Raised:
|
184
|
+
builtins\.AssertionError\(Result \(56\) must be divisible by 10\)
|
185
|
+
"""
|
186
|
+
),
|
187
|
+
flags=MULTILINE,
|
188
|
+
)
|
189
|
+
|
190
|
+
|
191
|
+
@fixture
|
192
|
+
def traceback_func_many_long() -> Pattern[str]:
|
193
|
+
return re.compile(
|
194
|
+
strip_and_dedent(
|
195
|
+
r"""
|
196
|
+
Date/time \| .+
|
197
|
+
Started \| .+
|
198
|
+
Duration \| .+
|
199
|
+
User \| .+
|
200
|
+
Host \| .+
|
201
|
+
Version \|\s
|
202
|
+
|
203
|
+
Frame 1/1: func_many \(tests.test_traceback_funcs.many\)
|
204
|
+
Inputs:
|
205
|
+
args\[0\] = 1
|
206
|
+
args\[1\] = 2
|
207
|
+
args\[2\] = 3
|
208
|
+
args\[3\] = 4
|
209
|
+
kwargs\[c\] = 5
|
210
|
+
kwargs\[d\] = 6
|
211
|
+
kwargs\[e\] = 7
|
212
|
+
Locals:
|
213
|
+
a = 2
|
214
|
+
b = 4
|
215
|
+
c = 10
|
216
|
+
args = \(
|
217
|
+
6,
|
218
|
+
8,
|
219
|
+
0,
|
220
|
+
2,
|
221
|
+
4,
|
222
|
+
6,
|
223
|
+
8,
|
224
|
+
10,
|
225
|
+
12,
|
226
|
+
14,
|
227
|
+
16,
|
228
|
+
18,
|
229
|
+
20,
|
230
|
+
22,
|
231
|
+
24,
|
232
|
+
26,
|
233
|
+
28,
|
234
|
+
30,
|
235
|
+
32,
|
236
|
+
34,
|
237
|
+
... \+82
|
238
|
+
\)
|
239
|
+
kwargs = {'d': 12, 'e': 14}
|
240
|
+
result = 9956
|
241
|
+
Line 16:
|
242
|
+
assert result % 10 == 0, f"Result \({result}\) must be divisible by 10"
|
243
|
+
Raised:
|
244
|
+
builtins\.AssertionError\(Result \(9956\) must be divisible by 10\)
|
245
|
+
"""
|
246
|
+
),
|
247
|
+
flags=MULTILINE,
|
248
|
+
)
|
249
|
+
|
250
|
+
|
251
|
+
@fixture
|
252
|
+
def traceback_func_many_short() -> Pattern[str]:
|
253
|
+
return re.compile(
|
254
|
+
strip_and_dedent(
|
255
|
+
r"""
|
256
|
+
Date/time \| .+
|
257
|
+
Started \| .+
|
258
|
+
Duration \| .+
|
259
|
+
User \| .+
|
260
|
+
Host \| .+
|
261
|
+
Version \|\s
|
262
|
+
|
263
|
+
Frame 1/1: func_many \(tests.test_traceback_funcs.many\)
|
264
|
+
Inputs:
|
265
|
+
args\[0\] = 1
|
266
|
+
args\[1\] = 2
|
267
|
+
args\[2\] = 3
|
268
|
+
args\[3\] = 4
|
269
|
+
kwargs\[c\] = 5
|
270
|
+
kwargs\[d\] = 6
|
271
|
+
kwargs\[e\] = 7
|
272
|
+
Locals:
|
273
|
+
a = 2
|
274
|
+
b = 4
|
275
|
+
c = 10
|
276
|
+
args = \(6, 8, 0, 2, 4, ... \+97\)
|
277
|
+
kwargs = {'d': 12, 'e': 14}
|
278
|
+
result = 9956
|
279
|
+
Line 16:
|
280
|
+
assert result % 10 == 0, f"Result \({result}\) must be divisible by 10"
|
281
|
+
Raised:
|
282
|
+
builtins\.AssertionError\(Result \(9956\) must be divisible by 10\)
|
283
|
+
"""
|
284
|
+
),
|
285
|
+
flags=MULTILINE,
|
286
|
+
)
|
287
|
+
|
288
|
+
|
289
|
+
@fixture
|
290
|
+
def traceback_func_task_group_one() -> Pattern[str]:
|
291
|
+
return re.compile(
|
292
|
+
strip_and_dedent(
|
293
|
+
r"""
|
294
|
+
Date/time \| .+
|
295
|
+
Started \| .+
|
296
|
+
Duration \| .+
|
297
|
+
User \| .+
|
298
|
+
Host \| .+
|
299
|
+
Version \|\s
|
300
|
+
|
301
|
+
Exception group:
|
302
|
+
Frame 1/1: func_task_group_one_first \(tests\.test_traceback_funcs\.task_group_one\)
|
303
|
+
Inputs:
|
304
|
+
args\[0\] = 1
|
305
|
+
args\[1\] = 2
|
306
|
+
args\[2\] = 3
|
307
|
+
args\[3\] = 4
|
308
|
+
kwargs\[c\] = 5
|
309
|
+
kwargs\[d\] = 6
|
310
|
+
kwargs\[e\] = 7
|
311
|
+
Locals:
|
312
|
+
a = 2
|
313
|
+
b = 4
|
314
|
+
c = 10
|
315
|
+
args = \(6, 8\)
|
316
|
+
kwargs = {'d': 12, 'e': 14}
|
317
|
+
tg = <TaskGroup cancelling>
|
318
|
+
_ = <Task finished name='Task-\d+' coro=<func_task_group_one_second\(\) done, defined at .+src.+utilities.+traceback\.py:\d+> exception=AssertionError\('Result \(112\) must be divisible by 10'\)>
|
319
|
+
Line 18:
|
320
|
+
async with TaskGroup\(\) as tg:
|
321
|
+
Raised:
|
322
|
+
builtins\.ExceptionGroup\(unhandled errors in a TaskGroup \(1 sub-exception\)\)
|
323
|
+
|
324
|
+
Exception group error 1/1:
|
325
|
+
Frame 1/1: func_task_group_one_second \(tests\.test_traceback_funcs\.task_group_one\)
|
326
|
+
Inputs:
|
327
|
+
args\[0\] = 2
|
328
|
+
args\[1\] = 4
|
329
|
+
args\[2\] = 6
|
330
|
+
args\[3\] = 8
|
331
|
+
kwargs\[c\] = 10
|
332
|
+
kwargs\[d\] = 12
|
333
|
+
kwargs\[e\] = 14
|
334
|
+
Locals:
|
335
|
+
a = 4
|
336
|
+
b = 8
|
337
|
+
c = 20
|
338
|
+
args = \(12, 16\)
|
339
|
+
kwargs = {'d': 24, 'e': 28}
|
340
|
+
result = 112
|
341
|
+
Line 33:
|
342
|
+
assert result % 10 == 0, f"Result \({result}\) must be divisible by 10"
|
343
|
+
Raised:
|
344
|
+
builtins\.AssertionError\(Result \(112\) must be divisible by 10\)
|
345
|
+
"""
|
346
|
+
)
|
347
|
+
)
|
348
|
+
|
349
|
+
|
350
|
+
@fixture
|
351
|
+
def traceback_func_two() -> Pattern[str]:
|
352
|
+
return re.compile(
|
353
|
+
strip_and_dedent(
|
354
|
+
r"""
|
355
|
+
Date/time \| .+
|
356
|
+
Started \| .+
|
357
|
+
Duration \| .+
|
358
|
+
User \| .+
|
359
|
+
Host \| .+
|
360
|
+
Version \|\s
|
361
|
+
|
362
|
+
Frame 1/2: func_two_first \(tests\.test_traceback_funcs\.two\)
|
363
|
+
Inputs:
|
364
|
+
args\[0\] = 1
|
365
|
+
args\[1\] = 2
|
366
|
+
args\[2\] = 3
|
367
|
+
args\[3\] = 4
|
368
|
+
kwargs\[c\] = 5
|
369
|
+
kwargs\[d\] = 6
|
370
|
+
kwargs\[e\] = 7
|
371
|
+
Locals:
|
372
|
+
a = 2
|
373
|
+
b = 4
|
374
|
+
c = 10
|
375
|
+
args = \(6, 8\)
|
376
|
+
kwargs = {'d': 12, 'e': 14}
|
377
|
+
Line 15:
|
378
|
+
return func_two_second\(a, b, \*args, c=c, \*\*kwargs\)
|
379
|
+
|
380
|
+
Frame 2/2: func_two_second \(tests\.test_traceback_funcs\.two\)
|
381
|
+
Inputs:
|
382
|
+
args\[0\] = 2
|
383
|
+
args\[1\] = 4
|
384
|
+
args\[2\] = 6
|
385
|
+
args\[3\] = 8
|
386
|
+
kwargs\[c\] = 10
|
387
|
+
kwargs\[d\] = 12
|
388
|
+
kwargs\[e\] = 14
|
389
|
+
Locals:
|
390
|
+
a = 4
|
391
|
+
b = 8
|
392
|
+
c = 20
|
393
|
+
args = \(12, 16\)
|
394
|
+
kwargs = {'d': 24, 'e': 28}
|
395
|
+
result = 112
|
396
|
+
Line 26:
|
397
|
+
assert result % 10 == 0, f"Result \({result}\) must be divisible by 10"
|
398
|
+
Raised:
|
399
|
+
builtins\.AssertionError\(Result \(112\) must be divisible by 10\)
|
400
|
+
"""
|
401
|
+
),
|
402
|
+
flags=MULTILINE,
|
403
|
+
)
|
404
|
+
|
405
|
+
|
406
|
+
@fixture
|
407
|
+
def traceback_func_untraced() -> Pattern[str]:
|
408
|
+
return re.compile(
|
409
|
+
strip_and_dedent(
|
410
|
+
r"""
|
411
|
+
Traceback \(most recent call last\):
|
412
|
+
|
413
|
+
File ".+src.+tests.+test_(logging|sys|traceback)\.py", line \d+, in test_.+
|
414
|
+
_ = func_untraced\(1, 2, 3, 4, c=5, d=6, e=7\)
|
415
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
416
|
+
|
417
|
+
File ".+src.+tests.+test_traceback_funcs.+untraced\.py", line 13, in func_untraced
|
418
|
+
assert result % 10 == 0, f"Result \({result}\) must be divisible by 10"
|
419
|
+
^^^^^^^^^^^^^^^^
|
420
|
+
|
421
|
+
AssertionError: Result \(56\) must be divisible by 10
|
422
|
+
"""
|
423
|
+
).replace("^", r"\^"),
|
424
|
+
flags=MULTILINE,
|
425
|
+
)
|
@@ -23,14 +23,12 @@ from hypothesis.strategies import (
|
|
23
23
|
sets,
|
24
24
|
timedeltas,
|
25
25
|
timezones,
|
26
|
-
uuids,
|
27
26
|
)
|
28
27
|
from luigi import Task
|
29
28
|
from numpy import inf, int64, isfinite, isinf, isnan, ravel, rint
|
30
29
|
from pathvalidate import validate_filepath
|
31
30
|
from pytest import mark, raises
|
32
|
-
from
|
33
|
-
from sqlalchemy.ext.asyncio import AsyncEngine
|
31
|
+
from whenever import Date, DateDelta, PlainDateTime, ZonedDateTime
|
34
32
|
|
35
33
|
from tests.conftest import SKIPIF_CI_AND_WINDOWS
|
36
34
|
from utilities.datetime import (
|
@@ -45,7 +43,6 @@ from utilities.datetime import (
|
|
45
43
|
)
|
46
44
|
from utilities.functions import ensure_int
|
47
45
|
from utilities.hypothesis import (
|
48
|
-
_SQLALCHEMY_ENGINE_DIALECTS,
|
49
46
|
MaybeSearchStrategy,
|
50
47
|
PlainDateTimesError,
|
51
48
|
Shape,
|
@@ -54,8 +51,10 @@ from utilities.hypothesis import (
|
|
54
51
|
_Draw2InputResolvedToSentinelError,
|
55
52
|
assume_does_not_raise,
|
56
53
|
bool_arrays,
|
54
|
+
date_deltas_whenever,
|
57
55
|
date_durations,
|
58
56
|
dates_two_digit_year,
|
57
|
+
dates_whenever,
|
59
58
|
datetime_durations,
|
60
59
|
draw2,
|
61
60
|
float32s,
|
@@ -77,13 +76,13 @@ from utilities.hypothesis import (
|
|
77
76
|
pairs,
|
78
77
|
paths,
|
79
78
|
plain_datetimes,
|
79
|
+
plain_datetimes_whenever,
|
80
80
|
random_states,
|
81
81
|
sentinels,
|
82
82
|
sets_fixed_length,
|
83
83
|
settings_with_reduced_examples,
|
84
84
|
setup_hypothesis_profiles,
|
85
85
|
slices,
|
86
|
-
sqlalchemy_engines,
|
87
86
|
str_arrays,
|
88
87
|
temp_dirs,
|
89
88
|
temp_paths,
|
@@ -99,6 +98,7 @@ from utilities.hypothesis import (
|
|
99
98
|
uint64s,
|
100
99
|
versions,
|
101
100
|
zoned_datetimes,
|
101
|
+
zoned_datetimes_whenever,
|
102
102
|
)
|
103
103
|
from utilities.math import (
|
104
104
|
MAX_FLOAT32,
|
@@ -119,7 +119,6 @@ from utilities.math import (
|
|
119
119
|
from utilities.os import temp_environ
|
120
120
|
from utilities.platform import maybe_yield_lower_case
|
121
121
|
from utilities.sentinel import Sentinel
|
122
|
-
from utilities.sqlalchemy import Dialect, _get_dialect
|
123
122
|
from utilities.version import Version
|
124
123
|
from utilities.whenever import (
|
125
124
|
MAX_SERIALIZABLE_TIMEDELTA,
|
@@ -134,7 +133,6 @@ from utilities.whenever import (
|
|
134
133
|
if TYPE_CHECKING:
|
135
134
|
from collections.abc import Iterable
|
136
135
|
from collections.abc import Set as AbstractSet
|
137
|
-
from uuid import UUID
|
138
136
|
from zoneinfo import ZoneInfo
|
139
137
|
|
140
138
|
from utilities.datetime import Month
|
@@ -185,6 +183,31 @@ class TestBoolArrays:
|
|
185
183
|
assert array.shape == shape
|
186
184
|
|
187
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
|
+
|
188
211
|
class TestDateDurations:
|
189
212
|
@given(
|
190
213
|
data=data(),
|
@@ -264,6 +287,20 @@ class TestDatesTwoDigitYear:
|
|
264
287
|
assert date.year == parsed
|
265
288
|
|
266
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
|
+
|
267
304
|
class TestDateTimeDurations:
|
268
305
|
@given(
|
269
306
|
data=data(),
|
@@ -847,6 +884,22 @@ class TestPlainDateTimes:
|
|
847
884
|
_ = data.draw(plain_datetimes(round_="standard"))
|
848
885
|
|
849
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
|
+
|
850
903
|
class TestRandomStates:
|
851
904
|
@given(data=data())
|
852
905
|
def test_main(self, *, data: DataObject) -> None:
|
@@ -917,38 +970,6 @@ class TestSlices:
|
|
917
970
|
_ = data.draw(slices(iter_len, slice_len=iter_len + 1))
|
918
971
|
|
919
972
|
|
920
|
-
class TestSQLAlchemyEngines:
|
921
|
-
@given(
|
922
|
-
data=data(),
|
923
|
-
name=uuids(),
|
924
|
-
dialect=_SQLALCHEMY_ENGINE_DIALECTS,
|
925
|
-
ids=sets(integers(0, 10), min_size=1),
|
926
|
-
)
|
927
|
-
@settings(phases={Phase.generate})
|
928
|
-
async def test_main(
|
929
|
-
self, *, data: DataObject, name: UUID, dialect: Dialect, ids: set[int]
|
930
|
-
) -> None:
|
931
|
-
table = Table(
|
932
|
-
f"test_{name}", MetaData(), Column("id_", Integer, primary_key=True)
|
933
|
-
)
|
934
|
-
engine = await sqlalchemy_engines(data, table, dialect=dialect)
|
935
|
-
assert isinstance(engine, AsyncEngine)
|
936
|
-
assert _get_dialect(engine) == dialect
|
937
|
-
if dialect == "sqlite":
|
938
|
-
database = engine.url.database
|
939
|
-
assert database is not None
|
940
|
-
assert not Path(database).exists()
|
941
|
-
async with engine.begin() as conn:
|
942
|
-
await conn.run_sync(table.metadata.create_all)
|
943
|
-
ins = insert(table).values([(id_,) for id_ in ids])
|
944
|
-
async with engine.begin() as conn:
|
945
|
-
_ = await conn.execute(ins)
|
946
|
-
sel = select(table.c["id_"])
|
947
|
-
async with engine.begin() as conn:
|
948
|
-
results = (await conn.execute(sel)).scalars().all()
|
949
|
-
assert set(results) == ids
|
950
|
-
|
951
|
-
|
952
973
|
class TestStrArrays:
|
953
974
|
@given(
|
954
975
|
data=data(),
|
@@ -1237,3 +1258,23 @@ class TestZonedDateTimes:
|
|
1237
1258
|
ZonedDateTimesError, match="Rounding requires a timedelta; got None"
|
1238
1259
|
):
|
1239
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
|