dycw-utilities 0.131.13__tar.gz → 0.131.15__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.13 → dycw_utilities-0.131.15}/PKG-INFO +1 -1
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/pyproject.toml +4 -2
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_hypothesis.py +0 -25
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_luigi.py +16 -31
- dycw_utilities-0.131.15/src/tests/test_typed_settings.py +97 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/__init__.py +1 -1
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/hypothesis.py +0 -81
- dycw_utilities-0.131.15/src/utilities/luigi.py +195 -0
- dycw_utilities-0.131.15/src/utilities/typed_settings.py +61 -0
- dycw_utilities-0.131.13/src/utilities/luigi.py +0 -228
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/.gitignore +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/LICENSE +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/README.md +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/__init__.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/conftest.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/__init__.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_missing/__init__.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_missing/module.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_with/__init__.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_with/outer_1.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_with/outer_2.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_without/__init__.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_without/module_1.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/package_without/module_2.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/standalone.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/modules/with_imports.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_aiolimiter.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_altair.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_asyncio.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_asyncio_classes/__init__.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_asyncio_classes/loopers.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_asyncio_classes/redis.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_atomicwrites.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_atools.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_cachetools.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_click.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_concurrent.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_contextlib.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_contextvars.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_cryptography.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_cvxpy.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_dataclasses.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_datetime.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_enum.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_errors.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_eventkit.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_fastapi.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_fpdf2.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_functions.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_functools.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_getpass.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_git.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_hashlib.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_http.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_importlib.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_inflect.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_ipython.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_iterables.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_jupyter.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_libcst.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_lightweight_charts.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_logging.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_math.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_memory_profiler.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_modules.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_more_itertools.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_numpy.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_operator.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_optuna.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_orjson.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_os.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_parse.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_pathlib.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_period.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_pickle.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_platform.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_polars.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_polars_ols.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_pottery.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_pqdm.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_psutil.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_pydantic.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_pyinstrument.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_pyrsistent.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_pytest.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_pytest_regressions.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_python_dotenv.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_random.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_re.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_redis.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_reprlib.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_scipy.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_sentinel.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_shelve.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_slack_sdk.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_socket.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_sqlalchemy.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_statsmodel.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_streamlit.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_string.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_tempfile.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_tenacity.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_text.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_threading.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_timer.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_traceback.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_types.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_typing.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_typing_funcs/__init__.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_typing_funcs/no_future.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_typing_funcs/with_future.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_tzdata.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_tzlocal.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_uuid.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_version.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_warnings.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_whenever.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_whenever2.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_zipfile.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/tests/test_zoneinfo.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/aiolimiter.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/altair.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/asyncio.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/atomicwrites.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/atools.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/cachetools.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/click.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/concurrent.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/contextlib.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/contextvars.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/cryptography.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/cvxpy.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/dataclasses.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/datetime.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/enum.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/errors.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/eventkit.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/fastapi.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/fpdf2.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/functions.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/functools.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/getpass.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/git.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/hashlib.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/http.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/importlib.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/inflect.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/ipython.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/iterables.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/jupyter.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/libcst.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/lightweight_charts.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/logging.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/math.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/memory_profiler.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/modules.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/more_itertools.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/numpy.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/operator.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/optuna.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/orjson.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/os.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/parse.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/pathlib.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/period.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/pickle.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/platform.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/polars.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/polars_ols.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/pottery.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/pqdm.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/psutil.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/py.typed +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/pydantic.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/pyinstrument.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/pyrsistent.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/pytest.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/pytest_regressions.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/python_dotenv.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/random.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/re.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/redis.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/reprlib.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/scipy.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/sentinel.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/shelve.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/slack_sdk.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/socket.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/sqlalchemy.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/statsmodels.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/streamlit.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/string.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/tempfile.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/tenacity.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/text.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/threading.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/timer.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/traceback.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/types.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/typing.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/tzdata.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/tzlocal.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/uuid.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/version.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/warnings.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/whenever.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/whenever2.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/zipfile.py +0 -0
- {dycw_utilities-0.131.13 → dycw_utilities-0.131.15}/src/utilities/zoneinfo.py +0 -0
@@ -61,6 +61,7 @@ dev = [
|
|
61
61
|
"streamlit >= 1.45.0, < 1.46",
|
62
62
|
"tenacity >= 8.5.0, < 9.0", # limited by luigi
|
63
63
|
"tomlkit >= 0.13.2, < 0.14",
|
64
|
+
"typed-settings >= 24.6.0, < 24.7",
|
64
65
|
"tzdata >= 2025.2, < 2025.3",
|
65
66
|
"uvicorn >= 0.34.1, < 0.35",
|
66
67
|
"vegafusion >= 2.0.2, < 2.1",
|
@@ -94,7 +95,7 @@ dependencies = [
|
|
94
95
|
name = "dycw-utilities"
|
95
96
|
readme = "README.md"
|
96
97
|
requires-python = ">= 3.12"
|
97
|
-
version = "0.131.
|
98
|
+
version = "0.131.15"
|
98
99
|
|
99
100
|
[project.optional-dependencies]
|
100
101
|
logging = [
|
@@ -121,7 +122,7 @@ test = [
|
|
121
122
|
# bump-my-version
|
122
123
|
[tool.bumpversion]
|
123
124
|
allow_dirty = true
|
124
|
-
current_version = "0.131.
|
125
|
+
current_version = "0.131.15"
|
125
126
|
|
126
127
|
[[tool.bumpversion.files]]
|
127
128
|
filename = "src/utilities/__init__.py"
|
@@ -319,6 +320,7 @@ select = [
|
|
319
320
|
"S101", # assert
|
320
321
|
"SLF001", # private-member-access
|
321
322
|
]
|
323
|
+
"src/tests/test_typed_settings.py" = ["I002"] # missing-required-import
|
322
324
|
"src/tests/test_typing_funcs/no_future.py" = ["I002"] # missing-required-import
|
323
325
|
|
324
326
|
[tool.ruff.lint.flake8-tidy-imports]
|
@@ -43,7 +43,6 @@ from utilities.datetime import (
|
|
43
43
|
)
|
44
44
|
from utilities.functions import ensure_int
|
45
45
|
from utilities.hypothesis import (
|
46
|
-
MaybeSearchStrategy,
|
47
46
|
PlainDateTimesError,
|
48
47
|
Shape,
|
49
48
|
ZonedDateTimesError,
|
@@ -67,7 +66,6 @@ from utilities.hypothesis import (
|
|
67
66
|
int64s,
|
68
67
|
int_arrays,
|
69
68
|
lists_fixed_length,
|
70
|
-
min_and_max_datetimes,
|
71
69
|
months,
|
72
70
|
namespace_mixins,
|
73
71
|
numbers,
|
@@ -704,29 +702,6 @@ class TestListsFixedLength:
|
|
704
702
|
assert sorted(result) == result
|
705
703
|
|
706
704
|
|
707
|
-
class TestMinAndMaxDateTimes:
|
708
|
-
@given(
|
709
|
-
data=data(),
|
710
|
-
min_value=zoned_datetimes() | none() | just(zoned_datetimes() | none()),
|
711
|
-
max_value=zoned_datetimes() | none() | just(zoned_datetimes() | none()),
|
712
|
-
)
|
713
|
-
def test_main(
|
714
|
-
self,
|
715
|
-
*,
|
716
|
-
data: DataObject,
|
717
|
-
min_value: MaybeSearchStrategy[dt.datetime | None],
|
718
|
-
max_value: MaybeSearchStrategy[dt.datetime | None],
|
719
|
-
) -> None:
|
720
|
-
min_datetime, max_datetime = data.draw(
|
721
|
-
min_and_max_datetimes(min_value=min_value, max_value=max_value)
|
722
|
-
)
|
723
|
-
assert min_datetime <= max_datetime
|
724
|
-
if isinstance(min_value, dt.datetime):
|
725
|
-
assert min_datetime == min_value
|
726
|
-
if isinstance(max_value, dt.datetime):
|
727
|
-
assert max_datetime == max_value
|
728
|
-
|
729
|
-
|
730
705
|
class TestMonths:
|
731
706
|
@given(data=data())
|
732
707
|
def test_main(self, *, data: DataObject) -> None:
|
@@ -1,28 +1,25 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from pathlib import Path
|
4
|
-
from typing import TYPE_CHECKING, Any, cast, override
|
4
|
+
from typing import TYPE_CHECKING, Any, Literal, cast, override
|
5
5
|
|
6
6
|
from hypothesis import given
|
7
|
-
from hypothesis.strategies import
|
8
|
-
from luigi import BoolParameter,
|
7
|
+
from hypothesis.strategies import booleans
|
8
|
+
from luigi import BoolParameter, Task
|
9
|
+
from pytest import mark, param
|
9
10
|
|
10
|
-
from utilities.hypothesis import namespace_mixins, temp_paths,
|
11
|
+
from utilities.hypothesis import namespace_mixins, temp_paths, zoned_datetimes_whenever
|
11
12
|
from utilities.luigi import (
|
12
|
-
DateHourParameter,
|
13
|
-
DateMinuteParameter,
|
14
|
-
DateSecondParameter,
|
15
13
|
ExternalFile,
|
16
14
|
ExternalTask,
|
17
15
|
PathTarget,
|
18
|
-
|
16
|
+
ZonedDateTimeParameter,
|
19
17
|
_ExternalTaskDummyTarget,
|
20
18
|
build,
|
21
19
|
)
|
22
|
-
from utilities.whenever import serialize_time, serialize_zoned_datetime
|
23
20
|
|
24
21
|
if TYPE_CHECKING:
|
25
|
-
|
22
|
+
from whenever import ZonedDateTime
|
26
23
|
|
27
24
|
|
28
25
|
class TestBuild:
|
@@ -34,20 +31,17 @@ class TestBuild:
|
|
34
31
|
|
35
32
|
|
36
33
|
class TestDateTimeParameter:
|
37
|
-
@given(
|
38
|
-
|
39
|
-
param_cls=sampled_from([
|
40
|
-
DateHourParameter,
|
41
|
-
DateMinuteParameter,
|
42
|
-
DateSecondParameter,
|
43
|
-
]),
|
44
|
-
datetime=zoned_datetimes(),
|
45
|
-
)
|
34
|
+
@given(datetime=zoned_datetimes_whenever())
|
35
|
+
@mark.parametrize("type_", [param("datetime"), param("str")])
|
46
36
|
def test_main(
|
47
|
-
self, *,
|
37
|
+
self, *, datetime: ZonedDateTime, type_: Literal["datetime", "str"]
|
48
38
|
) -> None:
|
49
|
-
param =
|
50
|
-
|
39
|
+
param = ZonedDateTimeParameter()
|
40
|
+
match type_:
|
41
|
+
case "datetime":
|
42
|
+
input_ = datetime
|
43
|
+
case "str":
|
44
|
+
input_ = datetime.format_common_iso()
|
51
45
|
norm = param.normalize(input_)
|
52
46
|
assert param.parse(param.serialize(norm)) == norm
|
53
47
|
|
@@ -90,12 +84,3 @@ class TestPathTarget:
|
|
90
84
|
assert not target.exists()
|
91
85
|
path.touch()
|
92
86
|
assert target.exists()
|
93
|
-
|
94
|
-
|
95
|
-
class TestTimeParameter:
|
96
|
-
@given(data=data(), time=times())
|
97
|
-
def test_main(self, *, data: DataObject, time: dt.time) -> None:
|
98
|
-
param = TimeParameter()
|
99
|
-
input_ = data.draw(sampled_from([time, serialize_time(time)]))
|
100
|
-
norm = param.normalize(input_)
|
101
|
-
assert param.parse(param.serialize(norm)) == time
|
@@ -0,0 +1,97 @@
|
|
1
|
+
from collections.abc import Callable
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from operator import eq
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import TypeVar
|
6
|
+
|
7
|
+
from hypothesis import given
|
8
|
+
from hypothesis.strategies import DataObject, SearchStrategy, data, tuples
|
9
|
+
from pytest import mark, param
|
10
|
+
from typed_settings import FileLoader, TomlFormat, load_settings
|
11
|
+
from whenever import Date, DateDelta, PlainDateTime, Time, TimeDelta, ZonedDateTime
|
12
|
+
|
13
|
+
from utilities.hypothesis import (
|
14
|
+
date_deltas_whenever,
|
15
|
+
dates_whenever,
|
16
|
+
plain_datetimes_whenever,
|
17
|
+
temp_paths,
|
18
|
+
text_ascii,
|
19
|
+
time_deltas_whenever,
|
20
|
+
times_whenever,
|
21
|
+
zoned_datetimes_whenever,
|
22
|
+
)
|
23
|
+
from utilities.typed_settings import ExtendedTSConverter
|
24
|
+
|
25
|
+
app_names = text_ascii(min_size=1).map(str.lower)
|
26
|
+
|
27
|
+
|
28
|
+
_T = TypeVar("_T")
|
29
|
+
|
30
|
+
|
31
|
+
class TestExtendedTSConverter:
|
32
|
+
@given(data=data(), root=temp_paths(), appname=text_ascii(min_size=1))
|
33
|
+
@mark.parametrize(
|
34
|
+
("test_cls", "strategy", "serialize"),
|
35
|
+
[
|
36
|
+
param(Date, dates_whenever(), Date.format_common_iso),
|
37
|
+
param(
|
38
|
+
DateDelta,
|
39
|
+
date_deltas_whenever(parsable=True),
|
40
|
+
DateDelta.format_common_iso,
|
41
|
+
),
|
42
|
+
param(
|
43
|
+
PlainDateTime,
|
44
|
+
plain_datetimes_whenever(),
|
45
|
+
PlainDateTime.format_common_iso,
|
46
|
+
),
|
47
|
+
param(Time, times_whenever(), Time.format_common_iso),
|
48
|
+
param(TimeDelta, time_deltas_whenever(), TimeDelta.format_common_iso),
|
49
|
+
param(
|
50
|
+
ZonedDateTime,
|
51
|
+
zoned_datetimes_whenever(),
|
52
|
+
ZonedDateTime.format_common_iso,
|
53
|
+
),
|
54
|
+
],
|
55
|
+
)
|
56
|
+
def test_main(
|
57
|
+
self,
|
58
|
+
*,
|
59
|
+
data: DataObject,
|
60
|
+
root: Path,
|
61
|
+
appname: str,
|
62
|
+
test_cls: type[_T],
|
63
|
+
strategy: SearchStrategy[_T],
|
64
|
+
serialize: Callable[[_T], str],
|
65
|
+
) -> None:
|
66
|
+
default, value = data.draw(tuples(strategy, strategy))
|
67
|
+
self._run_test(test_cls, default, root, appname, serialize, value, eq)
|
68
|
+
|
69
|
+
def _run_test(
|
70
|
+
self,
|
71
|
+
test_cls: type[_T],
|
72
|
+
default: _T,
|
73
|
+
root: Path,
|
74
|
+
appname: str,
|
75
|
+
serialize: Callable[[_T], str],
|
76
|
+
value: _T,
|
77
|
+
equal: Callable[[_T, _T], bool],
|
78
|
+
/,
|
79
|
+
) -> None:
|
80
|
+
@dataclass(frozen=True, kw_only=True, slots=True)
|
81
|
+
class Settings:
|
82
|
+
value: test_cls = default # pyright: ignore[reportInvalidTypeForm]
|
83
|
+
|
84
|
+
settings_default = load_settings(
|
85
|
+
Settings, loaders=[], converter=ExtendedTSConverter()
|
86
|
+
)
|
87
|
+
assert settings_default.value == default
|
88
|
+
_ = hash(settings_default)
|
89
|
+
file = Path(root, "file.toml")
|
90
|
+
with file.open(mode="w") as fh:
|
91
|
+
_ = fh.write(f'[{appname}]\nvalue = "{serialize(value)}"')
|
92
|
+
settings_loaded = load_settings(
|
93
|
+
Settings,
|
94
|
+
loaders=[FileLoader(formats={"*.toml": TomlFormat(appname)}, files=[file])],
|
95
|
+
converter=ExtendedTSConverter(),
|
96
|
+
)
|
97
|
+
assert equal(settings_loaded.value, value)
|
@@ -716,85 +716,6 @@ def lists_fixed_length(
|
|
716
716
|
##
|
717
717
|
|
718
718
|
|
719
|
-
@composite
|
720
|
-
def min_and_max_datetimes(
|
721
|
-
draw: DrawFn,
|
722
|
-
/,
|
723
|
-
*,
|
724
|
-
min_value: MaybeSearchStrategy[dt.datetime | None] = None,
|
725
|
-
max_value: MaybeSearchStrategy[dt.datetime | None] = None,
|
726
|
-
time_zone: MaybeSearchStrategy[ZoneInfo | timezone] = UTC,
|
727
|
-
round_: MathRoundMode | None = None,
|
728
|
-
timedelta: dt.timedelta | None = None,
|
729
|
-
rel_tol: float | None = None,
|
730
|
-
abs_tol: float | None = None,
|
731
|
-
valid: bool = False,
|
732
|
-
) -> tuple[dt.datetime, dt.datetime]:
|
733
|
-
"""Strategy for generating min/max datetimes."""
|
734
|
-
match min_value, max_value:
|
735
|
-
case None, None:
|
736
|
-
return draw(
|
737
|
-
pairs(
|
738
|
-
zoned_datetimes(
|
739
|
-
time_zone=time_zone,
|
740
|
-
round_=round_,
|
741
|
-
timedelta=timedelta,
|
742
|
-
rel_tol=rel_tol,
|
743
|
-
abs_tol=abs_tol,
|
744
|
-
valid=valid,
|
745
|
-
),
|
746
|
-
sorted=True,
|
747
|
-
)
|
748
|
-
)
|
749
|
-
case None, dt.datetime():
|
750
|
-
min_value_ = draw(
|
751
|
-
zoned_datetimes(
|
752
|
-
max_value=max_value,
|
753
|
-
time_zone=time_zone,
|
754
|
-
round_=round_,
|
755
|
-
timedelta=timedelta,
|
756
|
-
rel_tol=rel_tol,
|
757
|
-
abs_tol=abs_tol,
|
758
|
-
valid=valid,
|
759
|
-
)
|
760
|
-
)
|
761
|
-
return min_value_, max_value
|
762
|
-
case dt.datetime(), None:
|
763
|
-
max_value_ = draw(
|
764
|
-
zoned_datetimes(
|
765
|
-
min_value=min_value,
|
766
|
-
time_zone=time_zone,
|
767
|
-
round_=round_,
|
768
|
-
timedelta=timedelta,
|
769
|
-
rel_tol=rel_tol,
|
770
|
-
abs_tol=abs_tol,
|
771
|
-
valid=valid,
|
772
|
-
)
|
773
|
-
)
|
774
|
-
return min_value, max_value_
|
775
|
-
case dt.datetime(), dt.datetime():
|
776
|
-
_ = assume(min_value <= max_value)
|
777
|
-
return min_value, max_value
|
778
|
-
case _, _:
|
779
|
-
strategy = zoned_datetimes(
|
780
|
-
time_zone=time_zone,
|
781
|
-
round_=round_,
|
782
|
-
timedelta=timedelta,
|
783
|
-
rel_tol=rel_tol,
|
784
|
-
abs_tol=abs_tol,
|
785
|
-
valid=valid,
|
786
|
-
)
|
787
|
-
min_value_ = draw2(draw, min_value, strategy)
|
788
|
-
max_value_ = draw2(draw, max_value, strategy)
|
789
|
-
_ = assume(min_value_ <= max_value_)
|
790
|
-
return min_value_, max_value_
|
791
|
-
case _ as never:
|
792
|
-
assert_never(never)
|
793
|
-
|
794
|
-
|
795
|
-
##
|
796
|
-
|
797
|
-
|
798
719
|
@composite
|
799
720
|
def months(
|
800
721
|
draw: DrawFn,
|
@@ -1561,14 +1482,12 @@ __all__ = [
|
|
1561
1482
|
"int64s",
|
1562
1483
|
"int_arrays",
|
1563
1484
|
"lists_fixed_length",
|
1564
|
-
"min_and_max_datetimes",
|
1565
1485
|
"months",
|
1566
1486
|
"namespace_mixins",
|
1567
1487
|
"numbers",
|
1568
1488
|
"pairs",
|
1569
1489
|
"paths",
|
1570
1490
|
"plain_datetimes",
|
1571
|
-
"plain_datetimes",
|
1572
1491
|
"plain_datetimes_whenever",
|
1573
1492
|
"random_states",
|
1574
1493
|
"sentinels",
|
@@ -0,0 +1,195 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from abc import ABC, abstractmethod
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import (
|
6
|
+
TYPE_CHECKING,
|
7
|
+
Any,
|
8
|
+
Literal,
|
9
|
+
TypeVar,
|
10
|
+
assert_never,
|
11
|
+
cast,
|
12
|
+
overload,
|
13
|
+
override,
|
14
|
+
)
|
15
|
+
|
16
|
+
import luigi
|
17
|
+
from luigi import Parameter, PathParameter, Target, Task
|
18
|
+
from luigi import build as _build
|
19
|
+
from luigi.parameter import ParameterVisibility, _no_value
|
20
|
+
from whenever import ZonedDateTime
|
21
|
+
|
22
|
+
if TYPE_CHECKING:
|
23
|
+
from collections.abc import Callable, Iterable
|
24
|
+
|
25
|
+
from luigi.execution_summary import LuigiRunResult
|
26
|
+
|
27
|
+
from utilities.types import DateTimeRoundUnit, LogLevel, PathLike, ZonedDateTimeLike
|
28
|
+
|
29
|
+
|
30
|
+
_T = TypeVar("_T")
|
31
|
+
|
32
|
+
|
33
|
+
# parameters
|
34
|
+
|
35
|
+
|
36
|
+
class ZonedDateTimeParameter(Parameter):
|
37
|
+
"""A parameter which takes the value of a zoned datetime."""
|
38
|
+
|
39
|
+
_unit: DateTimeRoundUnit
|
40
|
+
_increment: int
|
41
|
+
|
42
|
+
@override
|
43
|
+
def __init__(
|
44
|
+
self,
|
45
|
+
default: Any = _no_value,
|
46
|
+
is_global: bool = False,
|
47
|
+
significant: bool = True,
|
48
|
+
description: str | None = None,
|
49
|
+
config_path: None = None,
|
50
|
+
positional: bool = True,
|
51
|
+
always_in_help: bool = False,
|
52
|
+
batch_method: Callable[[Iterable[_T]], _T] | None = None,
|
53
|
+
visibility: ParameterVisibility = ParameterVisibility.PUBLIC,
|
54
|
+
*,
|
55
|
+
unit: DateTimeRoundUnit = "second",
|
56
|
+
increment: int = 1,
|
57
|
+
) -> None:
|
58
|
+
super().__init__(
|
59
|
+
default,
|
60
|
+
is_global,
|
61
|
+
significant,
|
62
|
+
description,
|
63
|
+
config_path,
|
64
|
+
positional,
|
65
|
+
always_in_help,
|
66
|
+
batch_method,
|
67
|
+
visibility,
|
68
|
+
)
|
69
|
+
self._unit = unit
|
70
|
+
self._increment = increment
|
71
|
+
|
72
|
+
@override
|
73
|
+
def normalize(self, x: ZonedDateTimeLike) -> ZonedDateTime:
|
74
|
+
match x:
|
75
|
+
case ZonedDateTime() as date_time:
|
76
|
+
...
|
77
|
+
case str() as text:
|
78
|
+
date_time = ZonedDateTime.parse_common_iso(text)
|
79
|
+
case _ as never:
|
80
|
+
assert_never(never)
|
81
|
+
return date_time.round(self._unit, increment=self._increment, mode="floor")
|
82
|
+
|
83
|
+
@override
|
84
|
+
def parse(self, x: str) -> ZonedDateTime:
|
85
|
+
return ZonedDateTime.parse_common_iso(x)
|
86
|
+
|
87
|
+
@override
|
88
|
+
def serialize(self, x: ZonedDateTime) -> str:
|
89
|
+
return x.format_common_iso()
|
90
|
+
|
91
|
+
|
92
|
+
# targets
|
93
|
+
|
94
|
+
|
95
|
+
class PathTarget(Target):
|
96
|
+
"""A local target whose `path` attribute is a Pathlib instance."""
|
97
|
+
|
98
|
+
def __init__(self, path: PathLike, /) -> None:
|
99
|
+
super().__init__()
|
100
|
+
self.path = Path(path)
|
101
|
+
|
102
|
+
@override
|
103
|
+
def exists(self) -> bool: # pyright: ignore[reportIncompatibleMethodOverride]
|
104
|
+
"""Check if the target exists."""
|
105
|
+
return self.path.exists()
|
106
|
+
|
107
|
+
|
108
|
+
# tasks
|
109
|
+
|
110
|
+
|
111
|
+
class ExternalTask(ABC, luigi.ExternalTask):
|
112
|
+
"""An external task with `exists()` defined here."""
|
113
|
+
|
114
|
+
@abstractmethod
|
115
|
+
def exists(self) -> bool:
|
116
|
+
"""Predicate on which the external task is deemed to exist."""
|
117
|
+
msg = f"{self=}" # pragma: no cover
|
118
|
+
raise NotImplementedError(msg) # pragma: no cover
|
119
|
+
|
120
|
+
@override
|
121
|
+
def output(self) -> _ExternalTaskDummyTarget: # pyright: ignore[reportIncompatibleMethodOverride]
|
122
|
+
return _ExternalTaskDummyTarget(self)
|
123
|
+
|
124
|
+
|
125
|
+
class _ExternalTaskDummyTarget(Target):
|
126
|
+
"""Dummy target for `ExternalTask`."""
|
127
|
+
|
128
|
+
def __init__(self, task: ExternalTask, /) -> None:
|
129
|
+
super().__init__()
|
130
|
+
self._task = task
|
131
|
+
|
132
|
+
@override
|
133
|
+
def exists(self) -> bool: # pyright: ignore[reportIncompatibleMethodOverride]
|
134
|
+
return self._task.exists()
|
135
|
+
|
136
|
+
|
137
|
+
class ExternalFile(ExternalTask):
|
138
|
+
"""Await an external file on the local disk."""
|
139
|
+
|
140
|
+
path: Path = cast("Any", PathParameter())
|
141
|
+
|
142
|
+
@override
|
143
|
+
def exists(self) -> bool:
|
144
|
+
return self.path.exists()
|
145
|
+
|
146
|
+
|
147
|
+
# functions
|
148
|
+
|
149
|
+
|
150
|
+
@overload
|
151
|
+
def build(
|
152
|
+
task: Iterable[Task],
|
153
|
+
/,
|
154
|
+
*,
|
155
|
+
detailed_summary: Literal[False] = False,
|
156
|
+
local_scheduler: bool = False,
|
157
|
+
log_level: LogLevel | None = None,
|
158
|
+
workers: int | None = None,
|
159
|
+
) -> bool: ...
|
160
|
+
@overload
|
161
|
+
def build(
|
162
|
+
task: Iterable[Task],
|
163
|
+
/,
|
164
|
+
*,
|
165
|
+
detailed_summary: Literal[True],
|
166
|
+
local_scheduler: bool = False,
|
167
|
+
log_level: LogLevel | None = None,
|
168
|
+
workers: int | None = None,
|
169
|
+
) -> LuigiRunResult: ...
|
170
|
+
def build(
|
171
|
+
task: Iterable[Task],
|
172
|
+
/,
|
173
|
+
*,
|
174
|
+
detailed_summary: bool = False,
|
175
|
+
local_scheduler: bool = False,
|
176
|
+
log_level: LogLevel | None = None,
|
177
|
+
workers: int | None = None,
|
178
|
+
) -> bool | LuigiRunResult:
|
179
|
+
"""Build a set of tasks."""
|
180
|
+
return _build(
|
181
|
+
task,
|
182
|
+
detailed_summary=detailed_summary,
|
183
|
+
local_scheduler=local_scheduler,
|
184
|
+
**({} if log_level is None else {"log_level": log_level}),
|
185
|
+
**({} if workers is None else {"workers": workers}),
|
186
|
+
)
|
187
|
+
|
188
|
+
|
189
|
+
__all__ = [
|
190
|
+
"ExternalFile",
|
191
|
+
"ExternalTask",
|
192
|
+
"PathTarget",
|
193
|
+
"ZonedDateTimeParameter",
|
194
|
+
"build",
|
195
|
+
]
|
@@ -0,0 +1,61 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import TYPE_CHECKING, Any, TypeVar, override
|
4
|
+
|
5
|
+
from typed_settings.converters import TSConverter
|
6
|
+
from whenever import (
|
7
|
+
Date,
|
8
|
+
DateDelta,
|
9
|
+
DateTimeDelta,
|
10
|
+
PlainDateTime,
|
11
|
+
Time,
|
12
|
+
TimeDelta,
|
13
|
+
ZonedDateTime,
|
14
|
+
)
|
15
|
+
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
from collections.abc import Callable
|
18
|
+
|
19
|
+
|
20
|
+
_T = TypeVar("_T")
|
21
|
+
|
22
|
+
|
23
|
+
class ExtendedTSConverter(TSConverter):
|
24
|
+
"""An extension of the TSConverter for custom types."""
|
25
|
+
|
26
|
+
@override
|
27
|
+
def __init__(
|
28
|
+
self,
|
29
|
+
*,
|
30
|
+
resolve_paths: bool = True,
|
31
|
+
strlist_sep: str | Callable[[str], list] | None = ":",
|
32
|
+
) -> None:
|
33
|
+
super().__init__(resolve_paths=resolve_paths, strlist_sep=strlist_sep)
|
34
|
+
cases: list[tuple[type[Any], Callable[..., Any]]] = [
|
35
|
+
(Date, Date.parse_common_iso),
|
36
|
+
(DateDelta, DateDelta.parse_common_iso),
|
37
|
+
(DateTimeDelta, DateTimeDelta.parse_common_iso),
|
38
|
+
(PlainDateTime, PlainDateTime.parse_common_iso),
|
39
|
+
(Time, Time.parse_common_iso),
|
40
|
+
(TimeDelta, TimeDelta.parse_common_iso),
|
41
|
+
(ZonedDateTime, ZonedDateTime.parse_common_iso),
|
42
|
+
]
|
43
|
+
extras = {cls: _make_converter(cls, func) for cls, func in cases}
|
44
|
+
self.scalar_converters |= extras
|
45
|
+
|
46
|
+
|
47
|
+
def _make_converter(
|
48
|
+
cls: type[_T], parser: Callable[[str], _T], /
|
49
|
+
) -> Callable[[Any, type[Any]], Any]:
|
50
|
+
def hook(value: _T | str, _: type[_T] = cls, /) -> Any:
|
51
|
+
if not isinstance(value, (cls, str)): # pragma: no cover
|
52
|
+
msg = f"Invalid type {type(value).__name__!r}; expected '{cls.__name__}' or 'str'"
|
53
|
+
raise TypeError(msg)
|
54
|
+
if isinstance(value, str):
|
55
|
+
return parser(value)
|
56
|
+
return value
|
57
|
+
|
58
|
+
return hook
|
59
|
+
|
60
|
+
|
61
|
+
__all__ = ["ExtendedTSConverter"]
|