dycw-utilities 0.129.9__tar.gz → 0.129.14__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.129.9 → dycw_utilities-0.129.14}/PKG-INFO +14 -7
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/pyproject.toml +24 -11
- dycw_utilities-0.129.14/src/tests/test_aiolimiter.py +39 -0
- dycw_utilities-0.129.14/src/tests/test_git.py +27 -0
- dycw_utilities-0.129.14/src/tests/test_inflect.py +20 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_pathlib.py +21 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/__init__.py +1 -1
- dycw_utilities-0.129.14/src/utilities/aiolimiter.py +25 -0
- dycw_utilities-0.129.14/src/utilities/git.py +40 -0
- dycw_utilities-0.129.14/src/utilities/inflect.py +17 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/logging.py +9 -6
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/pathlib.py +12 -1
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/scipy.py +1 -1
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/.gitignore +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/LICENSE +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/README.md +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/__init__.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/conftest.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/__init__.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_missing/__init__.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_missing/module.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_with/__init__.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_with/outer_1.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_with/outer_2.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_without/__init__.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_without/module_1.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_without/module_2.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/standalone.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/with_imports.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_altair.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_asyncio.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_asyncio_classes/__init__.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_asyncio_classes/loopers.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_asyncio_classes/redis.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_atomicwrites.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_atools.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_cachetools.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_click.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_concurrent.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_contextlib.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_contextvars.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_cryptography.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_cvxpy.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_dataclasses.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_datetime.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_enum.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_errors.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_eventkit.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_fastapi.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_fpdf2.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_functions.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_functools.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_getpass.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_hashlib.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_http.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_hypothesis.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_importlib.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_ipython.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_iterables.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_jupyter.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_libcst.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_lightweight_charts.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_logging.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_loguru.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_luigi.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_math.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_memory_profiler.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_modules.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_more_itertools.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_numpy.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_operator.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_optuna.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_orjson.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_os.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_parse.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_period.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_pickle.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_platform.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_polars.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_polars_ols.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_pottery.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_pqdm.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_psutil.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_pydantic.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_pyinstrument.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_pyrsistent.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_pytest.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_pytest_regressions.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_python_dotenv.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_random.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_re.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_redis.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_reprlib.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_scipy.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_sentinel.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_shelve.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_slack_sdk.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_socket.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_sqlalchemy.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_statsmodel.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_streamlit.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_string.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_sys.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_tempfile.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_tenacity.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_text.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_threading.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_timer.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/__init__.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/chain.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/decorated_async.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/decorated_sync.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/error_bind.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/many.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/one.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/recursive.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/task_group_one.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/task_group_two.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/two.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_traceback_funcs/untraced.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_types.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_typing.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_typing_funcs/__init__.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_typing_funcs/no_future.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_typing_funcs/with_future.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_tzdata.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_tzlocal.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_uuid.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_version.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_warnings.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_whenever.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_zipfile.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_zoneinfo.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/altair.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/asyncio.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/atomicwrites.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/atools.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/cachetools.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/click.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/concurrent.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/contextlib.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/contextvars.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/cryptography.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/cvxpy.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/dataclasses.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/datetime.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/enum.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/errors.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/eventkit.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/fastapi.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/fpdf2.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/functions.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/functools.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/getpass.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/hashlib.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/http.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/hypothesis.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/importlib.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/ipython.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/iterables.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/jupyter.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/libcst.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/lightweight_charts.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/loguru.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/luigi.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/math.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/memory_profiler.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/modules.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/more_itertools.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/numpy.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/operator.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/optuna.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/orjson.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/os.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/parse.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/period.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/pickle.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/platform.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/polars.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/polars_ols.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/pottery.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/pqdm.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/psutil.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/py.typed +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/pydantic.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/pyinstrument.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/pyrsistent.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/pytest.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/pytest_regressions.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/python_dotenv.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/random.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/re.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/redis.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/reprlib.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/sentinel.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/shelve.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/slack_sdk.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/socket.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/sqlalchemy.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/statsmodels.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/streamlit.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/string.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/sys.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/tempfile.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/tenacity.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/text.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/threading.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/timer.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/traceback.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/types.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/typing.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/tzdata.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/tzlocal.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/uuid.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/version.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/warnings.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/whenever.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/zipfile.py +0 -0
- {dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/utilities/zoneinfo.py +0 -0
@@ -1,13 +1,18 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dycw-utilities
|
3
|
-
Version: 0.129.
|
3
|
+
Version: 0.129.14
|
4
4
|
Author-email: Derek Wan <d.wan@icloud.com>
|
5
5
|
License-File: LICENSE
|
6
6
|
Requires-Python: >=3.12
|
7
7
|
Requires-Dist: typing-extensions<4.15,>=4.14.0
|
8
|
+
Provides-Extra: logging
|
9
|
+
Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'logging'
|
10
|
+
Requires-Dist: coloredlogs<15.1,>=15.0.1; extra == 'logging'
|
11
|
+
Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'logging'
|
12
|
+
Requires-Dist: whenever<0.9,>=0.8.4; extra == 'logging'
|
8
13
|
Provides-Extra: test
|
9
14
|
Requires-Dist: dycw-pytest-only<2.2,>=2.1.1; extra == 'test'
|
10
|
-
Requires-Dist: hypothesis<6.136,>=6.135.
|
15
|
+
Requires-Dist: hypothesis<6.136,>=6.135.2; extra == 'test'
|
11
16
|
Requires-Dist: pytest-asyncio<1.1,>=1.0.0; extra == 'test'
|
12
17
|
Requires-Dist: pytest-cov<6.2,>=6.1.1; extra == 'test'
|
13
18
|
Requires-Dist: pytest-instafail<0.6,>=0.5.0; extra == 'test'
|
@@ -19,6 +24,8 @@ Requires-Dist: pytest-rng<1.1,>=1.0.0; extra == 'test'
|
|
19
24
|
Requires-Dist: pytest-timeout<2.5,>=2.4.0; extra == 'test'
|
20
25
|
Requires-Dist: pytest-xdist<3.8,>=3.7.0; extra == 'test'
|
21
26
|
Requires-Dist: pytest<8.4,>=8.3.5; extra == 'test'
|
27
|
+
Provides-Extra: zzz-test-aiolimiter
|
28
|
+
Requires-Dist: aiolimiter<1.3,>=1.2.1; extra == 'zzz-test-aiolimiter'
|
22
29
|
Provides-Extra: zzz-test-altair
|
23
30
|
Requires-Dist: altair<5.6,>=5.5.0; extra == 'zzz-test-altair'
|
24
31
|
Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-altair'
|
@@ -77,9 +84,9 @@ Provides-Extra: zzz-test-hypothesis
|
|
77
84
|
Requires-Dist: aiosqlite<0.22,>=0.21.0; extra == 'zzz-test-hypothesis'
|
78
85
|
Requires-Dist: asyncpg<0.31,>=0.30.0; extra == 'zzz-test-hypothesis'
|
79
86
|
Requires-Dist: greenlet<3.3,>=3.2.0; extra == 'zzz-test-hypothesis'
|
80
|
-
Requires-Dist: hypothesis<6.136,>=6.135.
|
87
|
+
Requires-Dist: hypothesis<6.136,>=6.135.2; extra == 'zzz-test-hypothesis'
|
81
88
|
Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-hypothesis'
|
82
|
-
Requires-Dist: numpy<2.
|
89
|
+
Requires-Dist: numpy<2.4,>=2.3.0; extra == 'zzz-test-hypothesis'
|
83
90
|
Requires-Dist: pathvalidate<3.3,>=3.2.3; extra == 'zzz-test-hypothesis'
|
84
91
|
Requires-Dist: redis<6.3,>=6.2.0; extra == 'zzz-test-hypothesis'
|
85
92
|
Requires-Dist: sqlalchemy<2.1,>=2.0.41; extra == 'zzz-test-hypothesis'
|
@@ -108,14 +115,14 @@ Provides-Extra: zzz-test-luigi
|
|
108
115
|
Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-luigi'
|
109
116
|
Requires-Dist: whenever<0.9,>=0.8.4; extra == 'zzz-test-luigi'
|
110
117
|
Provides-Extra: zzz-test-math
|
111
|
-
Requires-Dist: numpy<2.
|
118
|
+
Requires-Dist: numpy<2.4,>=2.3.0; extra == 'zzz-test-math'
|
112
119
|
Provides-Extra: zzz-test-memory-profiler
|
113
120
|
Requires-Dist: memory-profiler<0.62,>=0.61.0; extra == 'zzz-test-memory-profiler'
|
114
121
|
Provides-Extra: zzz-test-modules
|
115
122
|
Provides-Extra: zzz-test-more-itertools
|
116
123
|
Requires-Dist: more-itertools<10.8,>=10.7.0; extra == 'zzz-test-more-itertools'
|
117
124
|
Provides-Extra: zzz-test-numpy
|
118
|
-
Requires-Dist: numpy<2.
|
125
|
+
Requires-Dist: numpy<2.4,>=2.3.0; extra == 'zzz-test-numpy'
|
119
126
|
Provides-Extra: zzz-test-operator
|
120
127
|
Requires-Dist: polars-lts-cpu<1.31,>=1.30.0; extra == 'zzz-test-operator'
|
121
128
|
Requires-Dist: whenever<0.9,>=0.8.4; extra == 'zzz-test-operator'
|
@@ -172,7 +179,7 @@ Requires-Dist: scipy<1.16,>=1.15.3; extra == 'zzz-test-scipy'
|
|
172
179
|
Provides-Extra: zzz-test-sentinel
|
173
180
|
Provides-Extra: zzz-test-shelve
|
174
181
|
Provides-Extra: zzz-test-slack-sdk
|
175
|
-
Requires-Dist: aiohttp<3.
|
182
|
+
Requires-Dist: aiohttp<3.13,>=3.12.11; extra == 'zzz-test-slack-sdk'
|
176
183
|
Requires-Dist: slack-sdk<3.36,>=3.35.0; extra == 'zzz-test-slack-sdk'
|
177
184
|
Provides-Extra: zzz-test-socket
|
178
185
|
Provides-Extra: zzz-test-sqlalchemy
|
@@ -8,7 +8,8 @@ requires = ["hatchling"]
|
|
8
8
|
# dependency groups
|
9
9
|
[dependency-groups]
|
10
10
|
dev = [
|
11
|
-
"aiohttp >= 3.12.
|
11
|
+
"aiohttp >= 3.12.11, < 3.13", # for slack
|
12
|
+
"aiolimiter >= 1.2.1, < 1.3",
|
12
13
|
"aiosqlite >= 0.21.0, < 0.22",
|
13
14
|
"altair >= 5.5.0, < 5.6",
|
14
15
|
"asyncpg >= 0.30.0, < 0.31", # for sqlalchemy async
|
@@ -24,8 +25,9 @@ dev = [
|
|
24
25
|
"fpdf2 >= 2.8.3, < 2.9",
|
25
26
|
"greenlet >= 3.2.0, < 3.3", # for sqlalchemy async
|
26
27
|
"httpx >= 0.28.1, < 0.29", # for fastapi
|
27
|
-
"hypothesis >= 6.135.
|
28
|
+
"hypothesis >= 6.135.2, < 6.136",
|
28
29
|
"img2pdf >= 0.6.0, < 0.7",
|
30
|
+
"inflect >= 7.5.0, < 7.6",
|
29
31
|
"lightweight-charts >= 2.1, < 2.2",
|
30
32
|
"loguru >= 0.7.3, < 0.8",
|
31
33
|
"luigi >= 3.6.0, < 3.7",
|
@@ -33,7 +35,7 @@ dev = [
|
|
33
35
|
"more-itertools >= 10.7.0, < 10.8",
|
34
36
|
"nest-asyncio >= 1.6.0, < 1.7", # for sqlalchemy async
|
35
37
|
"nox >= 2025.2.9, < 2025.3",
|
36
|
-
"numpy >= 2.
|
38
|
+
"numpy >= 2.3.0, < 2.4",
|
37
39
|
"libcst >= 1.8.0, < 1.9",
|
38
40
|
"optuna >= 4.3.0, < 4.4",
|
39
41
|
"orjson >= 3.10.18, < 3.11",
|
@@ -82,6 +84,7 @@ dev = [
|
|
82
84
|
"pytest-xdist >= 3.7.0, < 3.8",
|
83
85
|
# CI
|
84
86
|
"win32_setctime >= 1.2.0, < 1.3", # https://github.com/Delgan/loguru/issues/147
|
87
|
+
"aiolimiter>=1.2.1",
|
85
88
|
]
|
86
89
|
|
87
90
|
# project
|
@@ -93,12 +96,18 @@ dependencies = [
|
|
93
96
|
name = "dycw-utilities"
|
94
97
|
readme = "README.md"
|
95
98
|
requires-python = ">= 3.12"
|
96
|
-
version = "0.129.
|
99
|
+
version = "0.129.14"
|
97
100
|
|
98
101
|
[project.optional-dependencies]
|
102
|
+
logging = [
|
103
|
+
"atomicwrites >= 1.4.1, < 1.5",
|
104
|
+
"coloredlogs >= 15.0.1, < 15.1",
|
105
|
+
"tzlocal >= 5.3.1, < 5.4",
|
106
|
+
"whenever >= 0.8.4, < 0.9",
|
107
|
+
]
|
99
108
|
test = [
|
100
109
|
"dycw-pytest-only >= 2.1.1, < 2.2",
|
101
|
-
"hypothesis >= 6.135.
|
110
|
+
"hypothesis >= 6.135.2, < 6.136",
|
102
111
|
"pytest >= 8.3.5, < 8.4",
|
103
112
|
"pytest-asyncio >= 1.0.0, < 1.1",
|
104
113
|
"pytest-cov >= 6.1.1, < 6.2",
|
@@ -111,6 +120,9 @@ test = [
|
|
111
120
|
"pytest-timeout >= 2.4.0, < 2.5",
|
112
121
|
"pytest-xdist >= 3.7.0, < 3.8",
|
113
122
|
]
|
123
|
+
zzz-test-aiolimiter = [
|
124
|
+
"aiolimiter >= 1.2.1, < 1.3",
|
125
|
+
]
|
114
126
|
zzz-test-altair = [
|
115
127
|
"altair >= 5.5.0, < 5.6",
|
116
128
|
"atomicwrites >= 1.4.1, < 1.5",
|
@@ -173,9 +185,9 @@ zzz-test-hypothesis = [
|
|
173
185
|
"aiosqlite >= 0.21.0, < 0.22",
|
174
186
|
"asyncpg >= 0.30.0, < 0.31", # for sqlalchemy async
|
175
187
|
"greenlet >= 3.2.0, < 3.3", # for sqlalchemy async
|
176
|
-
"hypothesis >= 6.135.
|
188
|
+
"hypothesis >= 6.135.2, < 6.136",
|
177
189
|
"luigi >= 3.6.0, < 3.7",
|
178
|
-
"numpy >= 2.
|
190
|
+
"numpy >= 2.3.0, < 2.4",
|
179
191
|
"pathvalidate >= 3.2.3, < 3.3",
|
180
192
|
"redis >= 6.2.0, < 6.3",
|
181
193
|
"sqlalchemy >= 2.0.41, < 2.1",
|
@@ -206,11 +218,11 @@ zzz-test-luigi = [
|
|
206
218
|
"luigi >= 3.6.0, < 3.7",
|
207
219
|
"whenever >= 0.8.4, < 0.9",
|
208
220
|
]
|
209
|
-
zzz-test-math = ["numpy >= 2.
|
221
|
+
zzz-test-math = ["numpy >= 2.3.0, < 2.4"]
|
210
222
|
zzz-test-memory-profiler = ["memory-profiler >= 0.61.0, < 0.62"]
|
211
223
|
zzz-test-modules = []
|
212
224
|
zzz-test-more-itertools = ["more-itertools >= 10.7.0, < 10.8"]
|
213
|
-
zzz-test-numpy = ["numpy >= 2.
|
225
|
+
zzz-test-numpy = ["numpy >= 2.3.0, < 2.4"]
|
214
226
|
zzz-test-operator = [
|
215
227
|
"polars-lts-cpu >= 1.30.0, < 1.31",
|
216
228
|
"whenever >= 0.8.4, < 0.9",
|
@@ -268,7 +280,7 @@ zzz-test-scipy = ["scipy >= 1.15.3, < 1.16"]
|
|
268
280
|
zzz-test-sentinel = []
|
269
281
|
zzz-test-shelve = []
|
270
282
|
zzz-test-slack-sdk = [
|
271
|
-
"aiohttp >= 3.12.
|
283
|
+
"aiohttp >= 3.12.11, < 3.13", # for slack
|
272
284
|
"slack-sdk >= 3.35.0, < 3.36",
|
273
285
|
]
|
274
286
|
zzz-test-socket = []
|
@@ -332,7 +344,7 @@ zzz-test-zoneinfo = [
|
|
332
344
|
# bump-my-version
|
333
345
|
[tool.bumpversion]
|
334
346
|
allow_dirty = true
|
335
|
-
current_version = "0.129.
|
347
|
+
current_version = "0.129.14"
|
336
348
|
|
337
349
|
[[tool.bumpversion.files]]
|
338
350
|
filename = "src/utilities/__init__.py"
|
@@ -443,6 +455,7 @@ filterwarnings = [
|
|
443
455
|
"ignore:Implicitly cleaning up <TemporaryDirectory '.*'>:ResourceWarning",
|
444
456
|
"ignore:ResourceTracker called reentrantly for resource cleanup, which is unsupported:UserWarning",
|
445
457
|
"ignore:Task .* without outputs has no custom complete.* method:UserWarning", # luigi
|
458
|
+
"ignore:The garbage collector is trying to clean up non-checked-in connection <AdaptedConnection <Connection(.*)>>:sqlalchemy.exc.SAWarning", # sqlalchemy
|
446
459
|
"ignore:There is no current event loop:DeprecationWarning", # eventkit
|
447
460
|
"ignore:Using fork.* can cause Polars to deadlock in the child process:RuntimeWarning", # polars/pqdm
|
448
461
|
"ignore:coroutine 'AsyncConnection.close' was never awaited:RuntimeWarning",
|
@@ -0,0 +1,39 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from asyncio import sleep
|
4
|
+
from typing import ClassVar
|
5
|
+
|
6
|
+
from utilities.aiolimiter import get_async_limiter
|
7
|
+
from utilities.text import unique_str
|
8
|
+
from utilities.timer import Timer
|
9
|
+
|
10
|
+
|
11
|
+
class TestGetAsyncLimiter:
|
12
|
+
async def test_main(self) -> None:
|
13
|
+
counter = 0
|
14
|
+
|
15
|
+
async def increment() -> None:
|
16
|
+
nonlocal counter
|
17
|
+
counter += 1
|
18
|
+
await sleep(0.01)
|
19
|
+
|
20
|
+
name = unique_str()
|
21
|
+
with Timer() as timer:
|
22
|
+
for _ in range(2):
|
23
|
+
async with get_async_limiter(name, rate=0.5):
|
24
|
+
await increment()
|
25
|
+
assert timer >= 0.48
|
26
|
+
|
27
|
+
shared: ClassVar[str] = unique_str()
|
28
|
+
|
29
|
+
async def test_shared1(self) -> None:
|
30
|
+
async with get_async_limiter(self.shared):
|
31
|
+
await sleep(0.01)
|
32
|
+
|
33
|
+
async def test_shared2(self) -> None:
|
34
|
+
async with get_async_limiter(self.shared):
|
35
|
+
await sleep(0.01)
|
36
|
+
|
37
|
+
async def test_shared3(self) -> None:
|
38
|
+
async with get_async_limiter(self.shared):
|
39
|
+
await sleep(0.01)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import TYPE_CHECKING
|
4
|
+
|
5
|
+
from hypothesis import given, settings
|
6
|
+
from pytest import raises
|
7
|
+
|
8
|
+
from utilities.git import GetRepoRootError, get_repo_root
|
9
|
+
from utilities.hypothesis import git_repos
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from pathlib import Path
|
13
|
+
|
14
|
+
|
15
|
+
class TestGetRepoRoot:
|
16
|
+
@given(repo=git_repos())
|
17
|
+
@settings(max_examples=1)
|
18
|
+
def test_main(self, *, repo: Path) -> None:
|
19
|
+
root = get_repo_root(path=repo)
|
20
|
+
expected = repo.resolve()
|
21
|
+
assert root == expected
|
22
|
+
|
23
|
+
def test_error(self, *, tmp_path: Path) -> None:
|
24
|
+
with raises(
|
25
|
+
GetRepoRootError, match="Path is not part of a `git` repository: .*"
|
26
|
+
):
|
27
|
+
_ = get_repo_root(path=tmp_path)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from pytest import mark, param
|
4
|
+
|
5
|
+
from utilities.inflect import counted_noun
|
6
|
+
|
7
|
+
|
8
|
+
class TestCountedNoun:
|
9
|
+
@mark.parametrize(
|
10
|
+
("num", "expected"),
|
11
|
+
[
|
12
|
+
param(0, "0 words"),
|
13
|
+
param(1, "1 word"),
|
14
|
+
param(2, "2 words"),
|
15
|
+
param(3, "3 words"),
|
16
|
+
],
|
17
|
+
)
|
18
|
+
def test_main(self, *, num: int, expected: str) -> None:
|
19
|
+
result = counted_noun(num, "word")
|
20
|
+
assert result == expected
|
@@ -8,11 +8,13 @@ from hypothesis import given, settings
|
|
8
8
|
from hypothesis.strategies import integers, sets
|
9
9
|
from pytest import mark, param, raises
|
10
10
|
|
11
|
+
from tests.conftest import SKIPIF_CI_AND_WINDOWS
|
11
12
|
from utilities.dataclasses import replace_non_sentinel
|
12
13
|
from utilities.hypothesis import git_repos, paths, temp_paths
|
13
14
|
from utilities.pathlib import (
|
14
15
|
GetRootError,
|
15
16
|
ensure_suffix,
|
17
|
+
expand_path,
|
16
18
|
get_path,
|
17
19
|
get_root,
|
18
20
|
list_dir,
|
@@ -40,6 +42,25 @@ class TestEnsureSuffix:
|
|
40
42
|
assert result == expected
|
41
43
|
|
42
44
|
|
45
|
+
class TestExpandPath:
|
46
|
+
@mark.parametrize(
|
47
|
+
("path", "expected"),
|
48
|
+
[
|
49
|
+
param("foo", Path("foo")),
|
50
|
+
param("~", Path.home()),
|
51
|
+
param("~/foo", Path.home().joinpath("foo")),
|
52
|
+
param("$HOME", Path.home(), marks=SKIPIF_CI_AND_WINDOWS),
|
53
|
+
param(
|
54
|
+
"$HOME/foo", Path.home().joinpath("foo"), marks=SKIPIF_CI_AND_WINDOWS
|
55
|
+
),
|
56
|
+
],
|
57
|
+
ids=str,
|
58
|
+
)
|
59
|
+
def test_main(self, *, path: Path, expected: Path) -> None:
|
60
|
+
result = expand_path(path)
|
61
|
+
assert result == expected
|
62
|
+
|
63
|
+
|
43
64
|
class TestGetPath:
|
44
65
|
@given(path=paths())
|
45
66
|
def test_path(self, *, path: Path) -> None:
|
@@ -0,0 +1,25 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from asyncio import get_running_loop
|
4
|
+
from typing import TYPE_CHECKING
|
5
|
+
|
6
|
+
from aiolimiter import AsyncLimiter
|
7
|
+
|
8
|
+
if TYPE_CHECKING:
|
9
|
+
from collections.abc import Hashable
|
10
|
+
|
11
|
+
_LIMITERS: dict[tuple[int, Hashable], AsyncLimiter] = {}
|
12
|
+
|
13
|
+
|
14
|
+
def get_async_limiter(key: Hashable, /, *, rate: float = 1.0) -> AsyncLimiter:
|
15
|
+
"""Get a loop-aware rate limiter."""
|
16
|
+
id_ = id(get_running_loop())
|
17
|
+
full = (id_, key)
|
18
|
+
try:
|
19
|
+
return _LIMITERS[full]
|
20
|
+
except KeyError:
|
21
|
+
limiter = _LIMITERS[full] = AsyncLimiter(1.0, time_period=rate)
|
22
|
+
return limiter
|
23
|
+
|
24
|
+
|
25
|
+
__all__ = ["get_async_limiter"]
|
@@ -0,0 +1,40 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from dataclasses import dataclass
|
4
|
+
from pathlib import Path
|
5
|
+
from re import IGNORECASE, search
|
6
|
+
from subprocess import PIPE, CalledProcessError, check_output
|
7
|
+
from typing import TYPE_CHECKING, override
|
8
|
+
|
9
|
+
from utilities.pathlib import PWD
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from utilities.types import PathLike
|
13
|
+
|
14
|
+
|
15
|
+
def get_repo_root(*, path: PathLike = PWD) -> Path:
|
16
|
+
"""Get the repo root."""
|
17
|
+
try:
|
18
|
+
output = check_output(
|
19
|
+
["git", "rev-parse", "--show-toplevel"], stderr=PIPE, cwd=path, text=True
|
20
|
+
)
|
21
|
+
except CalledProcessError as error:
|
22
|
+
# newer versions of git report "Not a git repository", whilst older
|
23
|
+
# versions report "not a git repository"
|
24
|
+
if search("fatal: not a git repository", error.stderr, flags=IGNORECASE):
|
25
|
+
raise GetRepoRootError(cwd=path) from error
|
26
|
+
raise # pragma: no cover
|
27
|
+
else:
|
28
|
+
return Path(output.strip("\n"))
|
29
|
+
|
30
|
+
|
31
|
+
@dataclass(kw_only=True, slots=True)
|
32
|
+
class GetRepoRootError(Exception):
|
33
|
+
cwd: PathLike
|
34
|
+
|
35
|
+
@override
|
36
|
+
def __str__(self) -> str:
|
37
|
+
return f"Path is not part of a `git` repository: {self.cwd}"
|
38
|
+
|
39
|
+
|
40
|
+
__all__ = ["GetRepoRootError", "get_repo_root"]
|
@@ -0,0 +1,17 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import cast
|
4
|
+
|
5
|
+
from inflect import Word, engine
|
6
|
+
|
7
|
+
_ENGINE = engine()
|
8
|
+
|
9
|
+
|
10
|
+
def counted_noun(num: int, noun: str, /) -> str:
|
11
|
+
"""Construct a counted noun."""
|
12
|
+
word = cast("Word", noun)
|
13
|
+
sin_or_plu = _ENGINE.plural_noun(word, count=num)
|
14
|
+
return f"{num} {sin_or_plu}"
|
15
|
+
|
16
|
+
|
17
|
+
__all__ = ["counted_noun"]
|
@@ -85,6 +85,9 @@ except ModuleNotFoundError: # pragma: no cover
|
|
85
85
|
type _When = Literal[
|
86
86
|
"S", "M", "H", "D", "midnight", "W0", "W1", "W2", "W3", "W4", "W5", "W6"
|
87
87
|
]
|
88
|
+
_BACKUP_COUNT: int = 100
|
89
|
+
_MAX_BYTES: int = 10 * 1024**2
|
90
|
+
_WHEN: _When = "D"
|
88
91
|
|
89
92
|
|
90
93
|
class SizeAndTimeRotatingFileHandler(BaseRotatingHandler):
|
@@ -100,10 +103,10 @@ class SizeAndTimeRotatingFileHandler(BaseRotatingHandler):
|
|
100
103
|
encoding: str | None = None,
|
101
104
|
delay: bool = False,
|
102
105
|
errors: Literal["strict", "ignore", "replace"] | None = None,
|
103
|
-
maxBytes: int =
|
104
|
-
when: _When =
|
106
|
+
maxBytes: int = _MAX_BYTES,
|
107
|
+
when: _When = _WHEN,
|
105
108
|
interval: int = 1,
|
106
|
-
backupCount: int =
|
109
|
+
backupCount: int = _BACKUP_COUNT,
|
107
110
|
utc: bool = False,
|
108
111
|
atTime: dt.time | None = None,
|
109
112
|
) -> None:
|
@@ -554,10 +557,10 @@ def setup_logging(
|
|
554
557
|
console_filters: Iterable[_FilterType] | None = None,
|
555
558
|
console_fmt: str = "❯ {_zoned_datetime_str} | {name}:{funcName}:{lineno} | {message}", # noqa: RUF001
|
556
559
|
files_dir: MaybeCallablePathLike | None = get_default_logging_path,
|
557
|
-
files_when: _When =
|
560
|
+
files_when: _When = _WHEN,
|
558
561
|
files_interval: int = 1,
|
559
|
-
files_backup_count: int =
|
560
|
-
files_max_bytes: int =
|
562
|
+
files_backup_count: int = _BACKUP_COUNT,
|
563
|
+
files_max_bytes: int = _MAX_BYTES,
|
561
564
|
files_filters: Iterable[_FilterType] | None = None,
|
562
565
|
files_fmt: str = "{_zoned_datetime_str} | {name}:{funcName}:{lineno} | {levelname:8} | {message}",
|
563
566
|
filters: MaybeIterable[_FilterType] | None = None,
|
@@ -5,6 +5,7 @@ from contextlib import contextmanager, suppress
|
|
5
5
|
from dataclasses import dataclass
|
6
6
|
from itertools import chain
|
7
7
|
from os import chdir
|
8
|
+
from os.path import expandvars
|
8
9
|
from pathlib import Path
|
9
10
|
from re import IGNORECASE, search
|
10
11
|
from subprocess import PIPE, CalledProcessError, check_output
|
@@ -34,6 +35,16 @@ def ensure_suffix(path: PathLike, suffix: str, /) -> Path:
|
|
34
35
|
##
|
35
36
|
|
36
37
|
|
38
|
+
def expand_path(path: PathLike, /) -> Path:
|
39
|
+
"""Expand a path."""
|
40
|
+
path = str(path)
|
41
|
+
path = expandvars(path)
|
42
|
+
return Path(path).expanduser()
|
43
|
+
|
44
|
+
|
45
|
+
##
|
46
|
+
|
47
|
+
|
37
48
|
@overload
|
38
49
|
def get_path(*, path: MaybeCallablePathLike | None) -> Path: ...
|
39
50
|
@overload
|
@@ -111,4 +122,4 @@ def temp_cwd(path: PathLike, /) -> Iterator[None]:
|
|
111
122
|
chdir(prev)
|
112
123
|
|
113
124
|
|
114
|
-
__all__ = ["PWD", "ensure_suffix", "get_path", "list_dir", "temp_cwd"]
|
125
|
+
__all__ = ["PWD", "ensure_suffix", "expand_path", "get_path", "list_dir", "temp_cwd"]
|
@@ -19,7 +19,7 @@ def _ppf_1d(array: NDArrayF, cutoff: float, /) -> NDArrayF:
|
|
19
19
|
out = full_like(array, nan, dtype=float)
|
20
20
|
out[j] = _ppf_1d(array[j], cutoff)
|
21
21
|
return out
|
22
|
-
low, high = min(
|
22
|
+
low, high = array.min(), array.max()
|
23
23
|
if is_zero(span := high - low):
|
24
24
|
return zeros_like(array, dtype=float)
|
25
25
|
centred = (array - low) / span
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_missing/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_missing/module.py
RENAMED
File without changes
|
{dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_with/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_with/outer_1.py
RENAMED
File without changes
|
{dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_with/outer_2.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_without/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_without/module_1.py
RENAMED
File without changes
|
{dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/modules/package_without/module_2.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_asyncio_classes/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.129.9 → dycw_utilities-0.129.14}/src/tests/test_asyncio_classes/loopers.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|