dycw-utilities 0.131.11__tar.gz → 0.131.13__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.13}/PKG-INFO +1 -1
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/pyproject.toml +2 -2
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/conftest.py +18 -2
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_atools.py +6 -5
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_cachetools.py +22 -9
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_dataclasses.py +3 -1
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_hypothesis.py +0 -55
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_logging.py +36 -65
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_orjson.py +39 -35
- dycw_utilities-0.131.13/src/tests/test_period.py +259 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_pyinstrument.py +1 -1
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_traceback.py +1 -1
- dycw_utilities-0.131.13/src/tests/test_tzdata.py +14 -0
- dycw_utilities-0.131.13/src/tests/test_tzlocal.py +15 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_whenever2.py +22 -3
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_zoneinfo.py +3 -5
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/__init__.py +1 -1
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/atools.py +7 -9
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/cachetools.py +8 -10
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/datetime.py +2 -9
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/fastapi.py +2 -4
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/fpdf2.py +2 -2
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/hypothesis.py +0 -136
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/logging.py +54 -52
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/orjson.py +46 -45
- dycw_utilities-0.131.13/src/utilities/period.py +154 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/pyinstrument.py +2 -3
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/traceback.py +18 -21
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/typing.py +25 -1
- dycw_utilities-0.131.13/src/utilities/tzdata.py +11 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/tzlocal.py +2 -26
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/whenever2.py +15 -2
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/zoneinfo.py +2 -2
- dycw_utilities-0.131.11/src/tests/test_period.py +0 -387
- dycw_utilities-0.131.11/src/tests/test_tzdata.py +0 -60
- dycw_utilities-0.131.11/src/tests/test_tzlocal.py +0 -45
- dycw_utilities-0.131.11/src/utilities/period.py +0 -324
- dycw_utilities-0.131.11/src/utilities/tzdata.py +0 -63
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/.gitignore +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/LICENSE +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/README.md +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_missing/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_missing/module.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_with/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_with/outer_1.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_with/outer_2.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_without/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_without/module_1.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/package_without/module_2.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/standalone.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/modules/with_imports.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_aiolimiter.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_altair.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_asyncio.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_asyncio_classes/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_asyncio_classes/loopers.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_asyncio_classes/redis.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_atomicwrites.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_click.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_concurrent.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_contextlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_contextvars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_cryptography.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_cvxpy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_datetime.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_enum.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_errors.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_eventkit.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_fastapi.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_fpdf2.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_functions.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_functools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_getpass.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_git.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_hashlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_http.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_importlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_inflect.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_ipython.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_iterables.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_jupyter.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_libcst.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_lightweight_charts.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_luigi.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_math.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_memory_profiler.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_modules.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_more_itertools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_numpy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_operator.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_optuna.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_os.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_parse.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_pathlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_pickle.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_platform.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_polars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_polars_ols.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_pottery.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_pqdm.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_psutil.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_pydantic.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_pyrsistent.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_pytest.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_pytest_regressions.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_python_dotenv.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_random.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_re.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_redis.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_reprlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_scipy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_sentinel.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_shelve.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_slack_sdk.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_socket.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_sqlalchemy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_statsmodel.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_streamlit.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_string.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_tempfile.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_tenacity.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_text.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_threading.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_timer.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_types.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_typing.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_typing_funcs/__init__.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_typing_funcs/no_future.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_typing_funcs/with_future.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_uuid.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_version.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_warnings.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_whenever.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/tests/test_zipfile.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/aiolimiter.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/altair.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/asyncio.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/atomicwrites.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/click.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/concurrent.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/contextlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/contextvars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/cryptography.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/cvxpy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/dataclasses.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/enum.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/errors.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/eventkit.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/functions.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/functools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/getpass.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/git.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/hashlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/http.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/importlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/inflect.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/ipython.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/iterables.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/jupyter.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/libcst.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/lightweight_charts.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/luigi.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/math.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/memory_profiler.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/modules.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/more_itertools.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/numpy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/operator.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/optuna.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/os.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/parse.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/pathlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/pickle.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/platform.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/polars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/polars_ols.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/pottery.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/pqdm.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/psutil.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/py.typed +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/pydantic.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/pyrsistent.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/pytest.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/pytest_regressions.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/python_dotenv.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/random.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/re.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/redis.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/reprlib.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/scipy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/sentinel.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/shelve.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/slack_sdk.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/socket.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/sqlalchemy.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/statsmodels.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/streamlit.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/string.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/tempfile.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/tenacity.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/text.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/threading.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/timer.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/types.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/uuid.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/version.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/warnings.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/whenever.py +0 -0
- {dycw_utilities-0.131.11 → dycw_utilities-0.131.13}/src/utilities/zipfile.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.13"
|
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.13"
|
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
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from asyncio import
|
4
|
-
|
3
|
+
from utilities.asyncio import sleep_dur
|
5
4
|
from utilities.atools import call_memoized
|
5
|
+
from utilities.whenever2 import SECOND
|
6
6
|
|
7
7
|
|
8
8
|
class TestCallMemoized:
|
@@ -20,6 +20,7 @@ class TestCallMemoized:
|
|
20
20
|
|
21
21
|
async def test_refresh(self) -> None:
|
22
22
|
counter = 0
|
23
|
+
delta = 0.05 * SECOND
|
23
24
|
|
24
25
|
async def increment() -> int:
|
25
26
|
nonlocal counter
|
@@ -27,9 +28,9 @@ class TestCallMemoized:
|
|
27
28
|
return counter
|
28
29
|
|
29
30
|
for _ in range(2):
|
30
|
-
assert (await call_memoized(increment,
|
31
|
+
assert (await call_memoized(increment, delta)) == 1
|
31
32
|
assert counter == 1
|
32
|
-
await
|
33
|
+
await sleep_dur(duration=2 * delta)
|
33
34
|
for _ in range(2):
|
34
|
-
assert (await call_memoized(increment,
|
35
|
+
assert (await call_memoized(increment, delta)) == 2
|
35
36
|
assert counter == 2
|
@@ -1,20 +1,32 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from
|
3
|
+
from typing import TYPE_CHECKING
|
4
4
|
|
5
5
|
from hypothesis import example, given
|
6
|
-
from hypothesis.strategies import
|
6
|
+
from hypothesis.strategies import integers, none
|
7
7
|
|
8
|
+
from utilities.asyncio import sleep_dur
|
8
9
|
from utilities.cachetools import TTLSet, cache
|
10
|
+
from utilities.hypothesis import time_deltas_whenever
|
11
|
+
from utilities.whenever2 import SECOND
|
12
|
+
|
13
|
+
if TYPE_CHECKING:
|
14
|
+
from whenever import TimeDelta
|
9
15
|
|
10
16
|
|
11
17
|
class TestCache:
|
12
18
|
@example(max_size=None, max_duration=None)
|
13
|
-
@example(max_size=None, max_duration=
|
19
|
+
@example(max_size=None, max_duration=SECOND)
|
14
20
|
@example(max_size=1, max_duration=None)
|
15
|
-
@example(max_size=1, max_duration=
|
16
|
-
@given(
|
17
|
-
|
21
|
+
@example(max_size=1, max_duration=SECOND)
|
22
|
+
@given(
|
23
|
+
max_size=integers(1, 10) | none(),
|
24
|
+
max_duration=time_deltas_whenever(
|
25
|
+
min_value=0.1 * SECOND, max_value=10.0 * SECOND
|
26
|
+
)
|
27
|
+
| none(),
|
28
|
+
)
|
29
|
+
def test_main(self, *, max_size: int, max_duration: TimeDelta) -> None:
|
18
30
|
counter = 0
|
19
31
|
|
20
32
|
@cache(max_size=max_size, max_duration=max_duration)
|
@@ -48,10 +60,11 @@ class TestTTLSet:
|
|
48
60
|
set_ = TTLSet(range(3))
|
49
61
|
assert len(set_) == 3
|
50
62
|
|
51
|
-
def test_max_duration(self) -> None:
|
52
|
-
|
63
|
+
async def test_max_duration(self) -> None:
|
64
|
+
delta = 0.1 * SECOND
|
65
|
+
set_ = TTLSet(range(3), max_duration=delta)
|
53
66
|
assert set_ == {0, 1, 2}
|
54
|
-
|
67
|
+
await sleep_dur(duration=2 * delta)
|
55
68
|
assert set_ == set()
|
56
69
|
|
57
70
|
def test_max_size(self) -> None:
|
@@ -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),
|
@@ -68,8 +68,6 @@ from utilities.hypothesis import (
|
|
68
68
|
int_arrays,
|
69
69
|
lists_fixed_length,
|
70
70
|
min_and_max_datetimes,
|
71
|
-
min_and_maybe_max_datetimes,
|
72
|
-
min_and_maybe_max_sizes,
|
73
71
|
months,
|
74
72
|
namespace_mixins,
|
75
73
|
numbers,
|
@@ -729,59 +727,6 @@ class TestMinAndMaxDateTimes:
|
|
729
727
|
assert max_datetime == max_value
|
730
728
|
|
731
729
|
|
732
|
-
class TestMinAndMaybeMaxDateTimes:
|
733
|
-
@given(
|
734
|
-
data=data(),
|
735
|
-
min_value=zoned_datetimes() | none() | just(zoned_datetimes() | none()),
|
736
|
-
max_value=zoned_datetimes()
|
737
|
-
| none()
|
738
|
-
| sentinels()
|
739
|
-
| just(zoned_datetimes() | none() | sentinels()),
|
740
|
-
)
|
741
|
-
def test_main(
|
742
|
-
self,
|
743
|
-
*,
|
744
|
-
data: DataObject,
|
745
|
-
min_value: MaybeSearchStrategy[dt.datetime | None],
|
746
|
-
max_value: MaybeSearchStrategy[dt.datetime | None | Sentinel],
|
747
|
-
) -> None:
|
748
|
-
min_datetime, max_datetime = data.draw(
|
749
|
-
min_and_maybe_max_datetimes(min_value=min_value, max_value=max_value)
|
750
|
-
)
|
751
|
-
assert (max_datetime is None) or (min_datetime <= max_datetime)
|
752
|
-
if isinstance(min_value, dt.datetime):
|
753
|
-
assert min_datetime == min_value
|
754
|
-
if isinstance(max_value, dt.datetime) or (max_value is None):
|
755
|
-
assert max_datetime == max_value
|
756
|
-
|
757
|
-
|
758
|
-
class TestMinAndMaybeMaxSizes:
|
759
|
-
@given(
|
760
|
-
data=data(),
|
761
|
-
min_value=integers(min_value=0) | none() | just(integers(min_value=0) | none()),
|
762
|
-
max_value=integers(min_value=0)
|
763
|
-
| none()
|
764
|
-
| sentinels()
|
765
|
-
| just(integers(min_value=0) | none() | sentinels()),
|
766
|
-
)
|
767
|
-
def test_main(
|
768
|
-
self,
|
769
|
-
*,
|
770
|
-
data: DataObject,
|
771
|
-
min_value: MaybeSearchStrategy[int | None],
|
772
|
-
max_value: MaybeSearchStrategy[int | None | Sentinel],
|
773
|
-
) -> None:
|
774
|
-
min_size, max_size = data.draw(
|
775
|
-
min_and_maybe_max_sizes(min_value=min_value, max_value=max_value)
|
776
|
-
)
|
777
|
-
assert min_size >= 0
|
778
|
-
assert (max_size is None) or (min_size <= max_size)
|
779
|
-
if isinstance(min_value, int):
|
780
|
-
assert min_size == min_value
|
781
|
-
if isinstance(max_value, int) or (max_value is None):
|
782
|
-
assert max_size == max_value
|
783
|
-
|
784
|
-
|
785
730
|
class TestMonths:
|
786
731
|
@given(data=data())
|
787
732
|
def test_main(self, *, data: DataObject) -> None:
|
@@ -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,16 @@ 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.tzlocal import
|
84
|
+
from utilities.tzlocal import LOCAL_TIME_ZONE
|
85
|
+
from utilities.whenever2 import MINUTE, SECOND, get_now
|
87
86
|
|
88
87
|
if TYPE_CHECKING:
|
89
88
|
from collections.abc import Sequence
|
90
89
|
|
90
|
+
from whenever import Date, ZonedDateTime
|
91
|
+
|
91
92
|
from utilities.types import Dataclass, StrMapping
|
92
93
|
|
93
94
|
|
@@ -169,7 +170,7 @@ class TestGetLogRecords:
|
|
169
170
|
"level": UInt64,
|
170
171
|
"path_name": String,
|
171
172
|
"line_num": UInt64,
|
172
|
-
"datetime": zoned_datetime(time_zone=
|
173
|
+
"datetime": zoned_datetime(time_zone=LOCAL_TIME_ZONE),
|
173
174
|
"func_name": String,
|
174
175
|
"stack_info": String,
|
175
176
|
"extra": Object,
|
@@ -195,9 +196,12 @@ class TestGetLogRecords:
|
|
195
196
|
level=sampled_from(get_args(LogLevel)) | none(),
|
196
197
|
min_level=sampled_from(get_args(LogLevel)) | none(),
|
197
198
|
max_level=sampled_from(get_args(LogLevel)) | none(),
|
198
|
-
|
199
|
-
|
200
|
-
|
199
|
+
date=dates_whenever() | none(),
|
200
|
+
min_date=dates_whenever() | none(),
|
201
|
+
max_date=dates_whenever() | none(),
|
202
|
+
datetime=zoned_datetimes_whenever() | none(),
|
203
|
+
min_datetime=zoned_datetimes_whenever() | none(),
|
204
|
+
max_datetime=zoned_datetimes_whenever() | none(),
|
201
205
|
func_name=booleans() | text_ascii() | none(),
|
202
206
|
extra=booleans() | text_ascii() | sets(text_ascii()) | none(),
|
203
207
|
log_file=booleans() | paths() | text_ascii() | none(),
|
@@ -218,9 +222,12 @@ class TestGetLogRecords:
|
|
218
222
|
level: LogLevel | None,
|
219
223
|
min_level: LogLevel | None,
|
220
224
|
max_level: LogLevel | None,
|
221
|
-
|
222
|
-
|
223
|
-
|
225
|
+
date: Date | None,
|
226
|
+
min_date: Date | None,
|
227
|
+
max_date: Date | None,
|
228
|
+
datetime: ZonedDateTime | None,
|
229
|
+
min_datetime: ZonedDateTime | None,
|
230
|
+
max_datetime: ZonedDateTime | None,
|
224
231
|
func_name: bool | str | None,
|
225
232
|
extra: bool | MaybeIterable[str] | None,
|
226
233
|
log_file: bool | PathLike | None,
|
@@ -245,9 +252,12 @@ class TestGetLogRecords:
|
|
245
252
|
level=level,
|
246
253
|
min_level=min_level,
|
247
254
|
max_level=max_level,
|
248
|
-
|
249
|
-
|
250
|
-
|
255
|
+
date=date,
|
256
|
+
min_date=min_date,
|
257
|
+
max_date=max_date,
|
258
|
+
datetime=datetime,
|
259
|
+
min_datetime=min_datetime,
|
260
|
+
max_datetime=max_datetime,
|
251
261
|
func_name=func_name,
|
252
262
|
extra=extra,
|
253
263
|
log_file=log_file,
|
@@ -272,24 +282,18 @@ class TestGetLogRecords:
|
|
272
282
|
assert all(r.level >= get_logging_level_number(min_level) for r in records)
|
273
283
|
if max_level is not None:
|
274
284
|
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)
|
285
|
+
if date is not None:
|
286
|
+
assert all(r.date == date for r in records)
|
287
|
+
if min_date is not None:
|
288
|
+
assert all(r.date >= min_date for r in records)
|
289
|
+
if max_date is not None:
|
290
|
+
assert all(r.date <= max_date for r in records)
|
291
|
+
if datetime is not None:
|
292
|
+
assert all(r.datetime == datetime for r in records)
|
293
|
+
if min_datetime is not None:
|
294
|
+
assert all(r.datetime >= min_datetime for r in records)
|
295
|
+
if max_datetime is not None:
|
296
|
+
assert all(r.datetime <= max_datetime for r in records)
|
293
297
|
if func_name is not None:
|
294
298
|
match func_name:
|
295
299
|
case bool() as has_func_name:
|
@@ -425,7 +429,7 @@ class TestOrjsonFormatter:
|
|
425
429
|
assert record.message == "message"
|
426
430
|
assert record.level == WARNING
|
427
431
|
assert record.path_name == Path(__file__)
|
428
|
-
assert abs(record.datetime -
|
432
|
+
assert abs(record.datetime - get_now()) <= SECOND
|
429
433
|
assert record.func_name == TestOrjsonFormatter.test_main.__name__
|
430
434
|
assert record.stack_info is None
|
431
435
|
assert record.extra == {"a": 1, "b": 2}
|