dycw-utilities 0.131.11__tar.gz → 0.131.12__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.11 → dycw_utilities-0.131.12}/PKG-INFO +1 -1
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/pyproject.toml +2 -2
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/conftest.py +18 -2
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_dataclasses.py +3 -1
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_logging.py +36 -65
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_orjson.py +37 -34
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_pyinstrument.py +1 -1
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_traceback.py +1 -1
- dycw_utilities-0.131.12/src/tests/test_tzlocal.py +15 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_whenever2.py +22 -3
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/__init__.py +1 -1
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/datetime.py +2 -9
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/fastapi.py +2 -4
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/fpdf2.py +2 -2
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/logging.py +54 -52
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/orjson.py +46 -45
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/pyinstrument.py +2 -3
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/traceback.py +18 -21
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/typing.py +25 -1
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/tzlocal.py +2 -26
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/whenever2.py +12 -0
- dycw_utilities-0.131.11/src/tests/test_tzlocal.py +0 -45
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/.gitignore +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/LICENSE +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/README.md +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_missing/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_missing/module.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_with/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_with/outer_1.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_with/outer_2.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_without/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_without/module_1.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/package_without/module_2.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/standalone.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/modules/with_imports.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_aiolimiter.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_altair.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_asyncio.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_asyncio_classes/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_asyncio_classes/loopers.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_asyncio_classes/redis.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_atomicwrites.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_atools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_cachetools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_click.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_concurrent.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_contextlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_contextvars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_cryptography.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_cvxpy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_datetime.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_enum.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_errors.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_eventkit.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_fastapi.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_fpdf2.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_functions.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_functools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_getpass.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_git.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_hashlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_http.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_hypothesis.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_importlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_inflect.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_ipython.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_iterables.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_jupyter.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_libcst.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_lightweight_charts.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_luigi.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_math.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_memory_profiler.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_modules.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_more_itertools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_numpy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_operator.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_optuna.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_os.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_parse.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_pathlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_period.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_pickle.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_platform.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_polars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_polars_ols.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_pottery.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_pqdm.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_psutil.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_pydantic.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_pyrsistent.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_pytest.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_pytest_regressions.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_python_dotenv.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_random.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_re.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_redis.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_reprlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_scipy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_sentinel.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_shelve.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_slack_sdk.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_socket.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_sqlalchemy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_statsmodel.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_streamlit.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_string.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_tempfile.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_tenacity.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_text.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_threading.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_timer.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_types.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_typing.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_typing_funcs/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_typing_funcs/no_future.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_typing_funcs/with_future.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_tzdata.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_uuid.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_version.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_warnings.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_whenever.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_zipfile.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/tests/test_zoneinfo.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/aiolimiter.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/altair.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/asyncio.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/atomicwrites.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/atools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/cachetools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/click.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/concurrent.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/contextlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/contextvars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/cryptography.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/cvxpy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/dataclasses.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/enum.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/errors.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/eventkit.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/functions.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/functools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/getpass.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/git.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/hashlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/http.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/hypothesis.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/importlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/inflect.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/ipython.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/iterables.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/jupyter.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/libcst.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/lightweight_charts.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/luigi.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/math.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/memory_profiler.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/modules.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/more_itertools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/numpy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/operator.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/optuna.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/os.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/parse.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/pathlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/period.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/pickle.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/platform.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/polars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/polars_ols.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/pottery.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/pqdm.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/psutil.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/py.typed +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/pydantic.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/pyrsistent.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/pytest.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/pytest_regressions.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/python_dotenv.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/random.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/re.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/redis.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/reprlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/scipy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/sentinel.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/shelve.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/slack_sdk.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/socket.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/sqlalchemy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/statsmodels.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/streamlit.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/string.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/tempfile.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/tenacity.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/text.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/threading.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/timer.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/types.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/tzdata.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/uuid.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/version.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/warnings.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/whenever.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/src/utilities/zipfile.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.12}/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.12"
|
98
98
|
|
99
99
|
[project.optional-dependencies]
|
100
100
|
logging = [
|
@@ -121,7 +121,7 @@ test = [
|
|
121
121
|
# bump-my-version
|
122
122
|
[tool.bumpversion]
|
123
123
|
allow_dirty = true
|
124
|
-
current_version = "0.131.
|
124
|
+
current_version = "0.131.12"
|
125
125
|
|
126
126
|
[[tool.bumpversion.files]]
|
127
127
|
filename = "src/utilities/__init__.py"
|
@@ -2,7 +2,8 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import re
|
4
4
|
from asyncio import sleep
|
5
|
-
from contextlib import suppress
|
5
|
+
from contextlib import AbstractContextManager, contextmanager, suppress
|
6
|
+
from logging import LogRecord, setLogRecordFactory
|
6
7
|
from os import environ
|
7
8
|
from re import MULTILINE, Pattern
|
8
9
|
from typing import TYPE_CHECKING, Any
|
@@ -16,7 +17,7 @@ from utilities.re import ExtractGroupError, extract_group
|
|
16
17
|
from utilities.text import strip_and_dedent
|
17
18
|
|
18
19
|
if TYPE_CHECKING:
|
19
|
-
from collections.abc import Sequence
|
20
|
+
from collections.abc import Iterator, Sequence
|
20
21
|
from pathlib import Path
|
21
22
|
|
22
23
|
from _pytest.fixtures import SubRequest
|
@@ -43,6 +44,21 @@ else:
|
|
43
44
|
setup_hypothesis_profiles()
|
44
45
|
|
45
46
|
|
47
|
+
# fixture - logging
|
48
|
+
|
49
|
+
|
50
|
+
@fixture
|
51
|
+
def set_log_factory() -> AbstractContextManager[None]:
|
52
|
+
@contextmanager
|
53
|
+
def cm() -> Iterator[None]:
|
54
|
+
try:
|
55
|
+
yield
|
56
|
+
finally:
|
57
|
+
setLogRecordFactory(LogRecord)
|
58
|
+
|
59
|
+
return cm()
|
60
|
+
|
61
|
+
|
46
62
|
# fixtures - sqlalchemy
|
47
63
|
|
48
64
|
|
@@ -928,7 +928,9 @@ class TestYieldFields:
|
|
928
928
|
assert get_args(args[0]) == ("true", "false")
|
929
929
|
|
930
930
|
def test_class_orjson_log_record(self) -> None:
|
931
|
-
result = list(
|
931
|
+
result = list(
|
932
|
+
yield_fields(OrjsonLogRecord, globalns=globals(), warn_name_errors=True)
|
933
|
+
)
|
932
934
|
exp_head = [
|
933
935
|
_YieldFieldsClass(name="name", type_=str, kw_only=True),
|
934
936
|
_YieldFieldsClass(name="message", type_=str, kw_only=True),
|
@@ -1,16 +1,8 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from asyncio import sleep
|
4
|
-
from contextlib import contextmanager
|
5
4
|
from io import StringIO
|
6
|
-
from logging import
|
7
|
-
Formatter,
|
8
|
-
Logger,
|
9
|
-
LogRecord,
|
10
|
-
StreamHandler,
|
11
|
-
getLogger,
|
12
|
-
setLogRecordFactory,
|
13
|
-
)
|
5
|
+
from logging import Formatter, Logger, StreamHandler, getLogger
|
14
6
|
from pathlib import Path
|
15
7
|
from re import search
|
16
8
|
from typing import TYPE_CHECKING, Any, cast
|
@@ -20,13 +12,12 @@ from hypothesis.strategies import booleans, integers, none, sampled_from
|
|
20
12
|
from pytest import LogCaptureFixture, mark, param, raises
|
21
13
|
|
22
14
|
from tests.conftest import SKIPIF_CI_AND_WINDOWS
|
23
|
-
from utilities.datetime import NOW_UTC, SECOND, serialize_compact
|
24
15
|
from utilities.hypothesis import (
|
25
16
|
assume_does_not_raise,
|
26
17
|
pairs,
|
27
18
|
temp_paths,
|
28
19
|
text_ascii,
|
29
|
-
|
20
|
+
zoned_datetimes_whenever,
|
30
21
|
)
|
31
22
|
from utilities.iterables import one
|
32
23
|
from utilities.logging import (
|
@@ -47,19 +38,14 @@ from utilities.logging import (
|
|
47
38
|
from utilities.text import unique_str
|
48
39
|
from utilities.types import LogLevel
|
49
40
|
from utilities.typing import get_args
|
41
|
+
from utilities.whenever2 import format_compact, get_now
|
50
42
|
|
51
43
|
if TYPE_CHECKING:
|
52
|
-
|
53
|
-
from
|
44
|
+
from collections.abc import Mapping
|
45
|
+
from contextlib import AbstractContextManager
|
54
46
|
from logging import _FilterType
|
55
47
|
|
56
|
-
|
57
|
-
@contextmanager
|
58
|
-
def _temp_log_factory() -> Iterator[None]:
|
59
|
-
try:
|
60
|
-
yield
|
61
|
-
finally:
|
62
|
-
setLogRecordFactory(LogRecord)
|
48
|
+
from whenever import ZonedDateTime
|
63
49
|
|
64
50
|
|
65
51
|
class TestAddFilters:
|
@@ -81,7 +67,6 @@ class TestAddFilters:
|
|
81
67
|
|
82
68
|
|
83
69
|
class TestBasicConfig:
|
84
|
-
@mark.parametrize("whenever", [param(True), param(False)])
|
85
70
|
@mark.parametrize(
|
86
71
|
"filters",
|
87
72
|
[
|
@@ -94,21 +79,20 @@ class TestBasicConfig:
|
|
94
79
|
self,
|
95
80
|
*,
|
96
81
|
caplog: LogCaptureFixture,
|
97
|
-
whenever: bool,
|
98
82
|
filters: _FilterType | None,
|
99
83
|
plain: bool,
|
84
|
+
set_log_factory: AbstractContextManager[None],
|
100
85
|
) -> None:
|
101
86
|
name = unique_str()
|
102
|
-
with
|
103
|
-
basic_config(obj=name,
|
104
|
-
|
105
|
-
|
106
|
-
|
87
|
+
with set_log_factory:
|
88
|
+
basic_config(obj=name, filters=filters, plain=plain)
|
89
|
+
getLogger(name).warning("message")
|
90
|
+
record = one(r for r in caplog.records if r.name == name)
|
91
|
+
assert record.message == "message"
|
107
92
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
basic_config(whenever=whenever)
|
93
|
+
def test_none(self, *, set_log_factory: AbstractContextManager[None]) -> None:
|
94
|
+
with set_log_factory:
|
95
|
+
basic_config()
|
112
96
|
|
113
97
|
|
114
98
|
class TestComputeRolloverActions:
|
@@ -208,7 +192,7 @@ class TestComputeRolloverActions:
|
|
208
192
|
|
209
193
|
await sleep(1)
|
210
194
|
tmp_path.joinpath("log.txt").touch()
|
211
|
-
now =
|
195
|
+
now = format_compact(get_now())
|
212
196
|
tmp_path.joinpath(f"log.99__{now}__{now}.txt").touch()
|
213
197
|
actions = _compute_rollover_actions(tmp_path, "log", ".txt")
|
214
198
|
assert len(actions.deletions) == 2
|
@@ -249,21 +233,20 @@ class TestFilterForKey:
|
|
249
233
|
|
250
234
|
|
251
235
|
class TestGetFormatter:
|
252
|
-
@mark.parametrize("whenever", [param(True), param(False)])
|
253
236
|
@mark.parametrize("plain", [param(True), param(False)])
|
254
237
|
@mark.parametrize("color_field_styles", [param({}), param(None)])
|
255
238
|
def test_main(
|
256
239
|
self,
|
257
240
|
*,
|
258
|
-
whenever: bool,
|
259
241
|
plain: bool,
|
260
242
|
color_field_styles: Mapping[str, _FieldStyleKeys] | None,
|
243
|
+
set_log_factory: AbstractContextManager[None],
|
261
244
|
) -> None:
|
262
|
-
with
|
245
|
+
with set_log_factory:
|
263
246
|
formatter = get_formatter(
|
264
|
-
|
247
|
+
plain=plain, color_field_styles=color_field_styles
|
265
248
|
)
|
266
|
-
|
249
|
+
assert isinstance(formatter, Formatter)
|
267
250
|
|
268
251
|
|
269
252
|
class TestGetLogger:
|
@@ -332,42 +315,35 @@ class TestRotatingLogFile:
|
|
332
315
|
assert result.start is None
|
333
316
|
assert result.end is None
|
334
317
|
|
335
|
-
@given(
|
336
|
-
index=integers(min_value=1),
|
337
|
-
end=zoned_datetimes(round_="standard", timedelta=SECOND),
|
338
|
-
)
|
318
|
+
@given(index=integers(min_value=1), end=zoned_datetimes_whenever())
|
339
319
|
def test_from_path_with_index_and_end(
|
340
|
-
self, *, index: int, end:
|
320
|
+
self, *, index: int, end: ZonedDateTime
|
341
321
|
) -> None:
|
342
|
-
path = Path(f"log.{index}__{
|
322
|
+
path = Path(f"log.{index}__{format_compact(end)}.txt")
|
343
323
|
result = _RotatingLogFile.from_path(path, "log", ".txt")
|
344
324
|
assert result is not None
|
345
325
|
assert result.stem == "log"
|
346
326
|
assert result.suffix == ".txt"
|
347
327
|
assert result.index == index
|
348
328
|
assert result.start is None
|
349
|
-
assert result.end == end
|
329
|
+
assert result.end == end.round()
|
350
330
|
|
351
331
|
@given(
|
352
332
|
index=integers(min_value=1),
|
353
|
-
datetimes=pairs(
|
354
|
-
zoned_datetimes(round_="standard", timedelta=SECOND), sorted=True
|
355
|
-
),
|
333
|
+
datetimes=pairs(zoned_datetimes_whenever(), sorted=True),
|
356
334
|
)
|
357
335
|
def test_from_path_with_index_start_and_end(
|
358
|
-
self, *, index: int, datetimes: tuple[
|
336
|
+
self, *, index: int, datetimes: tuple[ZonedDateTime, ZonedDateTime]
|
359
337
|
) -> None:
|
360
338
|
start, end = datetimes
|
361
|
-
path = Path(
|
362
|
-
f"log.{index}__{serialize_compact(start)}__{serialize_compact(end)}.txt"
|
363
|
-
)
|
339
|
+
path = Path(f"log.{index}__{format_compact(start)}__{format_compact(end)}.txt")
|
364
340
|
result = _RotatingLogFile.from_path(path, "log", ".txt")
|
365
341
|
assert result is not None
|
366
342
|
assert result.stem == "log"
|
367
343
|
assert result.suffix == ".txt"
|
368
344
|
assert result.index == index
|
369
|
-
assert result.start == start
|
370
|
-
assert result.end == end
|
345
|
+
assert result.start == start.round()
|
346
|
+
assert result.end == end.round()
|
371
347
|
|
372
348
|
def test_from_path_none(self) -> None:
|
373
349
|
path = Path("invalid.txt")
|
@@ -384,34 +360,30 @@ class TestRotatingLogFile:
|
|
384
360
|
assert file.path == root.joinpath(f"log.{index}.txt")
|
385
361
|
|
386
362
|
@given(
|
387
|
-
root=temp_paths(),
|
388
|
-
index=integers(min_value=1),
|
389
|
-
end=zoned_datetimes(round_="standard", timedelta=SECOND),
|
363
|
+
root=temp_paths(), index=integers(min_value=1), end=zoned_datetimes_whenever()
|
390
364
|
)
|
391
365
|
def test_path_with_index_and_end(
|
392
|
-
self, *, root: Path, index: int, end:
|
366
|
+
self, *, root: Path, index: int, end: ZonedDateTime
|
393
367
|
) -> None:
|
394
368
|
file = _RotatingLogFile(
|
395
369
|
directory=root, stem="log", suffix=".txt", index=index, end=end
|
396
370
|
)
|
397
|
-
assert file.path == root.joinpath(f"log.{index}__{
|
371
|
+
assert file.path == root.joinpath(f"log.{index}__{format_compact(end)}.txt")
|
398
372
|
|
399
373
|
@given(
|
400
374
|
root=temp_paths(),
|
401
375
|
index=integers(min_value=1),
|
402
|
-
datetimes=pairs(
|
403
|
-
zoned_datetimes(round_="standard", timedelta=SECOND), sorted=True
|
404
|
-
),
|
376
|
+
datetimes=pairs(zoned_datetimes_whenever(), sorted=True),
|
405
377
|
)
|
406
378
|
def test_path_with_index_start_and_end(
|
407
|
-
self, *, root: Path, index: int, datetimes: tuple[
|
379
|
+
self, *, root: Path, index: int, datetimes: tuple[ZonedDateTime, ZonedDateTime]
|
408
380
|
) -> None:
|
409
381
|
start, end = datetimes
|
410
382
|
file = _RotatingLogFile(
|
411
383
|
directory=root, stem="log", suffix=".txt", index=index, start=start, end=end
|
412
384
|
)
|
413
385
|
assert file.path == root.joinpath(
|
414
|
-
f"log.{index}__{
|
386
|
+
f"log.{index}__{format_compact(start)}__{format_compact(end)}.txt"
|
415
387
|
)
|
416
388
|
|
417
389
|
|
@@ -440,8 +412,7 @@ class TestSizeAndTimeRotatingFileHandler:
|
|
440
412
|
filename = tmp_path.joinpath("log")
|
441
413
|
logger.addHandler(SizeAndTimeRotatingFileHandler(filename=filename))
|
442
414
|
logger.warning("message")
|
443
|
-
|
444
|
-
content = fh.read()
|
415
|
+
content = filename.read_text()
|
445
416
|
assert content == "message\n"
|
446
417
|
|
447
418
|
def test_create_parents(self, *, tmp_path: Path) -> None:
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import datetime as dt
|
4
3
|
from collections.abc import Iterable
|
5
4
|
from io import StringIO
|
6
5
|
from logging import DEBUG, WARNING, FileHandler, StreamHandler, getLogger
|
@@ -12,7 +11,6 @@ from hypothesis import assume, given
|
|
12
11
|
from hypothesis.strategies import (
|
13
12
|
booleans,
|
14
13
|
builds,
|
15
|
-
dates,
|
16
14
|
dictionaries,
|
17
15
|
integers,
|
18
16
|
lists,
|
@@ -51,16 +49,16 @@ from tests.test_typing_funcs.with_future import (
|
|
51
49
|
DataClassFutureTypeLiteral,
|
52
50
|
DataClassFutureTypeLiteralNullable,
|
53
51
|
)
|
54
|
-
from utilities.datetime import MINUTE, SECOND, get_now
|
55
52
|
from utilities.functions import is_sequence_of
|
56
53
|
from utilities.hypothesis import (
|
57
54
|
assume_does_not_raise,
|
55
|
+
dates_whenever,
|
58
56
|
int64s,
|
59
57
|
paths,
|
60
58
|
temp_paths,
|
61
59
|
text_ascii,
|
62
60
|
text_printable,
|
63
|
-
|
61
|
+
zoned_datetimes_whenever,
|
64
62
|
)
|
65
63
|
from utilities.iterables import always_iterable, one
|
66
64
|
from utilities.logging import get_logging_level_number
|
@@ -81,13 +79,15 @@ from utilities.orjson import (
|
|
81
79
|
)
|
82
80
|
from utilities.polars import check_polars_dataframe, zoned_datetime
|
83
81
|
from utilities.sentinel import Sentinel, sentinel
|
84
|
-
from utilities.types import
|
82
|
+
from utilities.types import LogLevel, MaybeIterable, PathLike
|
85
83
|
from utilities.typing import get_args
|
86
|
-
from utilities.
|
84
|
+
from utilities.whenever2 import MINUTE, SECOND, get_now
|
87
85
|
|
88
86
|
if TYPE_CHECKING:
|
89
87
|
from collections.abc import Sequence
|
90
88
|
|
89
|
+
from whenever import Date, ZonedDateTime
|
90
|
+
|
91
91
|
from utilities.types import Dataclass, StrMapping
|
92
92
|
|
93
93
|
|
@@ -195,9 +195,12 @@ class TestGetLogRecords:
|
|
195
195
|
level=sampled_from(get_args(LogLevel)) | none(),
|
196
196
|
min_level=sampled_from(get_args(LogLevel)) | none(),
|
197
197
|
max_level=sampled_from(get_args(LogLevel)) | none(),
|
198
|
-
|
199
|
-
|
200
|
-
|
198
|
+
date=dates_whenever() | none(),
|
199
|
+
min_date=dates_whenever() | none(),
|
200
|
+
max_date=dates_whenever() | none(),
|
201
|
+
datetime=zoned_datetimes_whenever() | none(),
|
202
|
+
min_datetime=zoned_datetimes_whenever() | none(),
|
203
|
+
max_datetime=zoned_datetimes_whenever() | none(),
|
201
204
|
func_name=booleans() | text_ascii() | none(),
|
202
205
|
extra=booleans() | text_ascii() | sets(text_ascii()) | none(),
|
203
206
|
log_file=booleans() | paths() | text_ascii() | none(),
|
@@ -218,9 +221,12 @@ class TestGetLogRecords:
|
|
218
221
|
level: LogLevel | None,
|
219
222
|
min_level: LogLevel | None,
|
220
223
|
max_level: LogLevel | None,
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
+
date: Date | None,
|
225
|
+
min_date: Date | None,
|
226
|
+
max_date: Date | None,
|
227
|
+
datetime: ZonedDateTime | None,
|
228
|
+
min_datetime: ZonedDateTime | None,
|
229
|
+
max_datetime: ZonedDateTime | None,
|
224
230
|
func_name: bool | str | None,
|
225
231
|
extra: bool | MaybeIterable[str] | None,
|
226
232
|
log_file: bool | PathLike | None,
|
@@ -245,9 +251,12 @@ class TestGetLogRecords:
|
|
245
251
|
level=level,
|
246
252
|
min_level=min_level,
|
247
253
|
max_level=max_level,
|
248
|
-
|
249
|
-
|
250
|
-
|
254
|
+
date=date,
|
255
|
+
min_date=min_date,
|
256
|
+
max_date=max_date,
|
257
|
+
datetime=datetime,
|
258
|
+
min_datetime=min_datetime,
|
259
|
+
max_datetime=max_datetime,
|
251
260
|
func_name=func_name,
|
252
261
|
extra=extra,
|
253
262
|
log_file=log_file,
|
@@ -272,24 +281,18 @@ class TestGetLogRecords:
|
|
272
281
|
assert all(r.level >= get_logging_level_number(min_level) for r in records)
|
273
282
|
if max_level is not None:
|
274
283
|
assert all(r.level <= get_logging_level_number(max_level) for r in records)
|
275
|
-
if
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
if
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
if max_date_or_datetime is not None:
|
288
|
-
match max_date_or_datetime:
|
289
|
-
case dt.datetime() as max_datetime:
|
290
|
-
assert all(r.datetime <= max_datetime for r in records)
|
291
|
-
case dt.date() as max_date:
|
292
|
-
assert all(r.date <= max_date for r in records)
|
284
|
+
if date is not None:
|
285
|
+
assert all(r.date == date for r in records)
|
286
|
+
if min_date is not None:
|
287
|
+
assert all(r.date >= min_date for r in records)
|
288
|
+
if max_date is not None:
|
289
|
+
assert all(r.date <= max_date for r in records)
|
290
|
+
if datetime is not None:
|
291
|
+
assert all(r.datetime == datetime for r in records)
|
292
|
+
if min_datetime is not None:
|
293
|
+
assert all(r.datetime >= min_datetime for r in records)
|
294
|
+
if max_datetime is not None:
|
295
|
+
assert all(r.datetime <= max_datetime for r in records)
|
293
296
|
if func_name is not None:
|
294
297
|
match func_name:
|
295
298
|
case bool() as has_func_name:
|
@@ -425,7 +428,7 @@ class TestOrjsonFormatter:
|
|
425
428
|
assert record.message == "message"
|
426
429
|
assert record.level == WARNING
|
427
430
|
assert record.path_name == Path(__file__)
|
428
|
-
assert abs(record.datetime -
|
431
|
+
assert abs(record.datetime - get_now()) <= SECOND
|
429
432
|
assert record.func_name == TestOrjsonFormatter.test_main.__name__
|
430
433
|
assert record.stack_info is None
|
431
434
|
assert record.extra == {"a": 1, "b": 2}
|
@@ -99,7 +99,7 @@ class TestMakeExceptHook:
|
|
99
99
|
exc_type, exc_val, traceback = exc_info()
|
100
100
|
hook(exc_type, exc_val, traceback)
|
101
101
|
path = one(tmp_path.iterdir())
|
102
|
-
assert search(r"
|
102
|
+
assert search(r"^[\dT]+\.txt$", path.name)
|
103
103
|
|
104
104
|
def test_non_error(self) -> None:
|
105
105
|
hook = make_except_hook()
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from zoneinfo import ZoneInfo
|
4
|
+
|
5
|
+
from utilities.tzlocal import LOCAL_TIME_ZONE, LOCAL_TIME_ZONE_NAME, get_local_time_zone
|
6
|
+
|
7
|
+
|
8
|
+
class TestGetLocalTimeZone:
|
9
|
+
def test_function(self) -> None:
|
10
|
+
time_zone = get_local_time_zone()
|
11
|
+
assert isinstance(time_zone, ZoneInfo)
|
12
|
+
|
13
|
+
def test_constants(self) -> None:
|
14
|
+
assert isinstance(LOCAL_TIME_ZONE, ZoneInfo)
|
15
|
+
assert isinstance(LOCAL_TIME_ZONE_NAME, str)
|
@@ -8,14 +8,21 @@ from zoneinfo import ZoneInfo
|
|
8
8
|
from hypothesis import given
|
9
9
|
from hypothesis.strategies import just, none, timezones
|
10
10
|
from pytest import mark, param, raises
|
11
|
-
from whenever import
|
11
|
+
from whenever import (
|
12
|
+
Date,
|
13
|
+
DateDelta,
|
14
|
+
DateTimeDelta,
|
15
|
+
PlainDateTime,
|
16
|
+
TimeDelta,
|
17
|
+
ZonedDateTime,
|
18
|
+
)
|
12
19
|
|
13
20
|
from tests.conftest import IS_CI
|
14
21
|
from utilities.dataclasses import replace_non_sentinel
|
15
22
|
from utilities.hypothesis import dates_whenever, sentinels, zoned_datetimes_whenever
|
16
23
|
from utilities.sentinel import Sentinel, sentinel
|
17
24
|
from utilities.tzdata import HongKong, Tokyo
|
18
|
-
from utilities.tzlocal import
|
25
|
+
from utilities.tzlocal import LOCAL_TIME_ZONE_NAME
|
19
26
|
from utilities.whenever2 import (
|
20
27
|
DATE_DELTA_MAX,
|
21
28
|
DATE_DELTA_MIN,
|
@@ -39,6 +46,7 @@ from utilities.whenever2 import (
|
|
39
46
|
ZONED_DATE_TIME_MAX,
|
40
47
|
ZONED_DATE_TIME_MIN,
|
41
48
|
WheneverLogRecord,
|
49
|
+
format_compact,
|
42
50
|
from_timestamp,
|
43
51
|
from_timestamp_millis,
|
44
52
|
from_timestamp_nanos,
|
@@ -56,6 +64,17 @@ if TYPE_CHECKING:
|
|
56
64
|
from utilities.types import MaybeCallableDate, MaybeCallableZonedDateTime
|
57
65
|
|
58
66
|
|
67
|
+
class TestFormatCompact:
|
68
|
+
@given(datetime=zoned_datetimes_whenever())
|
69
|
+
def test_main(self, *, datetime: ZonedDateTime) -> None:
|
70
|
+
result = format_compact(datetime)
|
71
|
+
assert isinstance(result, str)
|
72
|
+
parsed = PlainDateTime.parse_common_iso(result)
|
73
|
+
assert parsed.nanosecond == 0
|
74
|
+
expected = datetime.round().to_tz(LOCAL_TIME_ZONE_NAME).to_plain()
|
75
|
+
assert parsed == expected
|
76
|
+
|
77
|
+
|
59
78
|
class TestFromTimeStamp:
|
60
79
|
@given(datetime=zoned_datetimes_whenever(time_zone=UTC if IS_CI else timezones()))
|
61
80
|
def test_main(self, *, datetime: ZonedDateTime) -> None:
|
@@ -100,7 +119,7 @@ class TestGetNowLocal:
|
|
100
119
|
|
101
120
|
def test_constant(self) -> None:
|
102
121
|
assert isinstance(NOW_LOCAL, ZonedDateTime)
|
103
|
-
assert NOW_LOCAL.tz ==
|
122
|
+
assert NOW_LOCAL.tz == LOCAL_TIME_ZONE_NAME
|
104
123
|
|
105
124
|
|
106
125
|
class TestGetToday:
|
@@ -21,21 +21,14 @@ from utilities.iterables import OneEmptyError, one
|
|
21
21
|
from utilities.math import SafeRoundError, round_, safe_round
|
22
22
|
from utilities.platform import SYSTEM
|
23
23
|
from utilities.sentinel import Sentinel, sentinel
|
24
|
-
from utilities.types import MaybeStr
|
24
|
+
from utilities.types import MaybeCallablePyDate, MaybeCallablePyDateTime, MaybeStr
|
25
25
|
from utilities.typing import is_instance_gen
|
26
26
|
from utilities.zoneinfo import UTC, ensure_time_zone, get_time_zone_name
|
27
27
|
|
28
28
|
if TYPE_CHECKING:
|
29
29
|
from collections.abc import Iterator
|
30
30
|
|
31
|
-
from utilities.types import
|
32
|
-
DateOrDateTime,
|
33
|
-
Duration,
|
34
|
-
MathRoundMode,
|
35
|
-
MaybeCallablePyDate,
|
36
|
-
MaybeCallablePyDateTime,
|
37
|
-
TimeZoneLike,
|
38
|
-
)
|
31
|
+
from utilities.types import DateOrDateTime, Duration, MathRoundMode, TimeZoneLike
|
39
32
|
|
40
33
|
|
41
34
|
_DAYS_PER_YEAR = 365.25
|
@@ -9,8 +9,7 @@ from uvicorn import Config, Server
|
|
9
9
|
|
10
10
|
from utilities.asyncio import Looper
|
11
11
|
from utilities.datetime import SECOND, datetime_duration_to_float
|
12
|
-
from utilities.
|
13
|
-
from utilities.whenever import serialize_zoned_datetime # skipif-ci
|
12
|
+
from utilities.whenever2 import get_now_local
|
14
13
|
|
15
14
|
if TYPE_CHECKING:
|
16
15
|
from types import TracebackType
|
@@ -31,8 +30,7 @@ class _PingerReceiverApp(FastAPI):
|
|
31
30
|
|
32
31
|
@self.get("/ping") # skipif-ci
|
33
32
|
def ping() -> str:
|
34
|
-
|
35
|
-
return f"pong @ {now}" # skipif-ci
|
33
|
+
return f"pong @ {get_now_local()}" # skipif-ci
|
36
34
|
|
37
35
|
_ = ping # skipif-ci
|
38
36
|
|
@@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, override
|
|
6
6
|
from fpdf import FPDF
|
7
7
|
from fpdf.enums import XPos, YPos
|
8
8
|
|
9
|
-
from utilities.
|
9
|
+
from utilities.whenever2 import format_compact, get_now
|
10
10
|
|
11
11
|
if TYPE_CHECKING:
|
12
12
|
from collections.abc import Iterator
|
@@ -47,7 +47,7 @@ def yield_pdf(*, header: str | None = None) -> Iterator[_BasePDF]:
|
|
47
47
|
def footer(self) -> None:
|
48
48
|
self.set_y(-15)
|
49
49
|
self.set_font(family="Helvetica", style="I", size=8)
|
50
|
-
page_no, now = self.page_no(),
|
50
|
+
page_no, now = self.page_no(), format_compact(get_now())
|
51
51
|
text = f"page {page_no}/{{}}; {now}"
|
52
52
|
_ = self.cell(
|
53
53
|
w=0,
|