dycw-utilities 0.165.1__tar.gz → 0.165.3__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.165.1 → dycw_utilities-0.165.3}/PKG-INFO +1 -1
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/pyproject.toml +2 -2
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_polars.py +90 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_typing.py +90 -11
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_typing_funcs/no_future.py +11 -1
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_typing_funcs/with_future.py +6 -1
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/__init__.py +1 -1
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/polars.py +30 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/typing.py +53 -10
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/.gitignore +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/LICENSE +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/README.md +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/__init__.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/conftest.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/__init__.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_missing/__init__.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_missing/module.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_with/__init__.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_with/outer_1.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_with/outer_2.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_without/__init__.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_without/module_1.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_without/module_2.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/standalone.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/with_imports.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_aeventkit.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_altair.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_asyncio.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_atomicwrites.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_atools.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_cachetools.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_click.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_concurrent.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_contextlib.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_contextvars.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_cryptography.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_cvxpy.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_dataclasses.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_enum.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_errors.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_fastapi.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_fpdf2.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_functions.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_functools.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_getpass.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_gzip.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_hashlib.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_http.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_hypothesis.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_importlib.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_inflect.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_ipython.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_iterables.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_json.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_jupyter.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_libcst.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_lightweight_charts.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_logging.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_math.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_memory_profiler.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_modules.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_more_itertools.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_numpy.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_objects/__init__.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_objects/objects.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_operator.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_optuna.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_orjson.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_os.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_parse.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_pathlib.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_pickle.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_platform.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_polars_ols.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_postgres.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_pottery.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_pqdm.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_psutil.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_pyinstrument.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_pytest.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_pytest_randomly.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_pytest_regressions.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_random.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_re.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_redis.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_reprlib.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_scipy.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_sentinel.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_shelve.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_slack_sdk.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_socket.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_sqlalchemy.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_statsmodels.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_string.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_tempfile.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_testbook.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_text.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_threading.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_timer.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_traceback.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_typed_settings.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_types.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_typing_funcs/__init__.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_tzdata.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_tzlocal.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_uuid.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_version.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_warnings.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_whenever.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_zipfile.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_zoneinfo.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/aeventkit.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/altair.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/asyncio.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/atomicwrites.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/atools.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/cachetools.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/click.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/concurrent.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/contextlib.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/contextvars.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/cryptography.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/cvxpy.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/dataclasses.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/enum.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/errors.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/fastapi.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/fpdf2.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/functions.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/functools.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/getpass.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/gzip.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/hashlib.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/http.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/hypothesis.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/importlib.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/inflect.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/ipython.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/iterables.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/json.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/jupyter.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/libcst.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/lightweight_charts.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/logging.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/math.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/memory_profiler.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/modules.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/more_itertools.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/numpy.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/operator.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/optuna.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/orjson.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/os.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/parse.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/pathlib.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/pickle.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/platform.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/polars_ols.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/postgres.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/pottery.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/pqdm.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/psutil.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/py.typed +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/pyinstrument.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/pytest.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/pytest_plugins/__init__.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/pytest_plugins/pytest_randomly.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/pytest_plugins/pytest_regressions.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/pytest_regressions.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/random.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/re.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/redis.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/reprlib.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/scipy.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/sentinel.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/shelve.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/slack_sdk.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/socket.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/sqlalchemy.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/statsmodels.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/string.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/tempfile.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/testbook.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/text.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/threading.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/timer.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/traceback.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/typed_settings.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/types.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/tzdata.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/tzlocal.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/uuid.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/version.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/warnings.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/whenever.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/zipfile.py +0 -0
- {dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/utilities/zoneinfo.py +0 -0
@@ -233,7 +233,7 @@ dependencies = [
|
|
233
233
|
name = "dycw-utilities"
|
234
234
|
readme = "README.md"
|
235
235
|
requires-python = ">= 3.12"
|
236
|
-
version = "0.165.
|
236
|
+
version = "0.165.3"
|
237
237
|
|
238
238
|
[project.entry-points.pytest11]
|
239
239
|
pytest-randomly = "utilities.pytest_plugins.pytest_randomly"
|
@@ -266,7 +266,7 @@ test = [
|
|
266
266
|
# bump-my-version
|
267
267
|
[tool.bumpversion]
|
268
268
|
allow_dirty = true
|
269
|
-
current_version = "0.165.
|
269
|
+
current_version = "0.165.3"
|
270
270
|
|
271
271
|
[[tool.bumpversion.files]]
|
272
272
|
filename = "src/utilities/__init__.py"
|
@@ -194,6 +194,7 @@ from utilities.polars import (
|
|
194
194
|
reify_exprs,
|
195
195
|
replace_time_zone,
|
196
196
|
round_to_float,
|
197
|
+
search_period,
|
197
198
|
select_exact,
|
198
199
|
serialize_dataframe,
|
199
200
|
serialize_series,
|
@@ -224,6 +225,7 @@ from utilities.whenever import (
|
|
224
225
|
get_now,
|
225
226
|
get_now_plain,
|
226
227
|
get_today,
|
228
|
+
to_zoned_date_time,
|
227
229
|
)
|
228
230
|
from utilities.zoneinfo import UTC, to_time_zone_name
|
229
231
|
|
@@ -2474,6 +2476,94 @@ class TestRoundToFloat:
|
|
2474
2476
|
_ = round_to_float(cast("Any", x), cast("Any", y))
|
2475
2477
|
|
2476
2478
|
|
2479
|
+
class TestSearchPeriod:
|
2480
|
+
@mark.parametrize(
|
2481
|
+
("time", "exp_start", "exp_end"),
|
2482
|
+
[
|
2483
|
+
param(whenever.Time(8, 58), None, None),
|
2484
|
+
param(whenever.Time(8, 59), None, None),
|
2485
|
+
param(whenever.Time(9), 0, None),
|
2486
|
+
param(whenever.Time(9, 1), 0, 0),
|
2487
|
+
param(whenever.Time(9, 59), 0, 0),
|
2488
|
+
param(whenever.Time(10), 1, 0),
|
2489
|
+
param(whenever.Time(10, 1), 1, 1),
|
2490
|
+
param(whenever.Time(10, 59), 1, 1),
|
2491
|
+
param(whenever.Time(11), 2, 1),
|
2492
|
+
param(whenever.Time(11, 1), 2, 2),
|
2493
|
+
param(whenever.Time(11, 59), 2, 2),
|
2494
|
+
param(whenever.Time(12), None, 2),
|
2495
|
+
param(whenever.Time(12, 1), None, None),
|
2496
|
+
param(whenever.Time(12, 59), None, None),
|
2497
|
+
param(whenever.Time(13), 3, None),
|
2498
|
+
param(whenever.Time(13, 1), 3, 3),
|
2499
|
+
param(whenever.Time(13, 59), 3, 3),
|
2500
|
+
param(whenever.Time(14), None, 3),
|
2501
|
+
param(whenever.Time(14, 1), None, None),
|
2502
|
+
param(whenever.Time(14, 59), None, None),
|
2503
|
+
param(whenever.Time(15), 4, None),
|
2504
|
+
param(whenever.Time(15, 1), 4, 4),
|
2505
|
+
param(whenever.Time(15, 59), 4, 4),
|
2506
|
+
param(whenever.Time(16), None, 4),
|
2507
|
+
param(whenever.Time(16, 1), None, None),
|
2508
|
+
param(whenever.Time(16, 2), None, None),
|
2509
|
+
],
|
2510
|
+
)
|
2511
|
+
@mark.parametrize("start_or_end", [param("start"), param("end")])
|
2512
|
+
def test_main(
|
2513
|
+
self,
|
2514
|
+
*,
|
2515
|
+
time: whenever.Time,
|
2516
|
+
start_or_end: Literal["start", "end"],
|
2517
|
+
exp_start: int | None,
|
2518
|
+
exp_end: int | None,
|
2519
|
+
) -> None:
|
2520
|
+
date = whenever.Date(2000, 1, 1)
|
2521
|
+
sr = DataFrame(
|
2522
|
+
data=[
|
2523
|
+
(
|
2524
|
+
date.at(whenever.Time(s)).py_datetime(),
|
2525
|
+
date.at(whenever.Time(e)).py_datetime(),
|
2526
|
+
)
|
2527
|
+
for s, e in [(9, 10), (10, 11), (11, 12), (13, 14), (15, 16)]
|
2528
|
+
],
|
2529
|
+
schema={"start": DatetimeUTC, "end": DatetimeUTC},
|
2530
|
+
orient="row",
|
2531
|
+
).with_columns(datetime=struct("start", "end"))["datetime"]
|
2532
|
+
assert len(sr) == 5
|
2533
|
+
date_time = date.at(time).assume_tz(UTC.key)
|
2534
|
+
match start_or_end:
|
2535
|
+
case "start":
|
2536
|
+
expected = exp_start
|
2537
|
+
case "end":
|
2538
|
+
expected = exp_end
|
2539
|
+
case never:
|
2540
|
+
assert_never(never)
|
2541
|
+
index = search_period(sr, date_time, start_or_end=start_or_end)
|
2542
|
+
if expected is None:
|
2543
|
+
assert index is None
|
2544
|
+
else:
|
2545
|
+
assert index is not None
|
2546
|
+
assert 0 <= index <= (len(sr) - 1)
|
2547
|
+
start, end = map(
|
2548
|
+
to_zoned_date_time, cast("Iterable[dt.datetime]", sr[index].values())
|
2549
|
+
)
|
2550
|
+
match start_or_end:
|
2551
|
+
case "start":
|
2552
|
+
assert start <= date_time < end
|
2553
|
+
case "end":
|
2554
|
+
assert start < date_time <= end
|
2555
|
+
case never:
|
2556
|
+
assert_never(never)
|
2557
|
+
if index > 0:
|
2558
|
+
prev_end = to_zoned_date_time(cast("dt.datetime", sr[index - 1]["end"]))
|
2559
|
+
assert prev_end <= date_time
|
2560
|
+
if index < (len(sr) - 1):
|
2561
|
+
next_start = to_zoned_date_time(
|
2562
|
+
cast("dt.datetime", sr[index + 1]["start"])
|
2563
|
+
)
|
2564
|
+
assert date_time <= next_start
|
2565
|
+
|
2566
|
+
|
2477
2567
|
class TestSelectExact:
|
2478
2568
|
df: ClassVar[DataFrame] = DataFrame(
|
2479
2569
|
data=[(True, False), (False, None), (None, True)],
|
@@ -10,9 +10,11 @@ from typing import (
|
|
10
10
|
TYPE_CHECKING,
|
11
11
|
Any,
|
12
12
|
Final,
|
13
|
+
ForwardRef,
|
13
14
|
Literal,
|
14
15
|
NamedTuple,
|
15
|
-
|
16
|
+
NotRequired,
|
17
|
+
_TypedDictMeta, # pyright: ignore[reportAttributeAccessIssue]
|
16
18
|
assert_never,
|
17
19
|
)
|
18
20
|
from uuid import UUID
|
@@ -50,6 +52,8 @@ from tests.test_typing_funcs.no_future import (
|
|
50
52
|
DataClassNoFutureNestedInnerFirstOuter,
|
51
53
|
DataClassNoFutureNestedOuterFirstInner,
|
52
54
|
DataClassNoFutureNestedOuterFirstOuter,
|
55
|
+
TypedDictNoFutureIntFloat,
|
56
|
+
TypedDictNoFutureIntFloatOptional,
|
53
57
|
)
|
54
58
|
from tests.test_typing_funcs.with_future import (
|
55
59
|
DataClassFutureDate,
|
@@ -80,10 +84,11 @@ from tests.test_typing_funcs.with_future import (
|
|
80
84
|
TrueOrFalseFutureLit,
|
81
85
|
TrueOrFalseFutureTypeLit,
|
82
86
|
TypedDictFutureIntFloat,
|
87
|
+
TypedDictFutureIntFloatOptional,
|
83
88
|
)
|
84
89
|
from utilities.hypothesis import text_ascii
|
85
90
|
from utilities.sentinel import Sentinel
|
86
|
-
from utilities.types import LogLevel, Number, Parallelism, Seed
|
91
|
+
from utilities.types import LogLevel, Number, Parallelism, Seed, StrMapping
|
87
92
|
from utilities.typing import (
|
88
93
|
IsInstanceGenError,
|
89
94
|
IsSubclassGenError,
|
@@ -92,6 +97,7 @@ from utilities.typing import (
|
|
92
97
|
_GetUnionTypeClassesInternalTypeError,
|
93
98
|
_GetUnionTypeClassesUnionTypeError,
|
94
99
|
get_args,
|
100
|
+
get_forward_ref_args,
|
95
101
|
get_literal_elements,
|
96
102
|
get_type_classes,
|
97
103
|
get_type_hints,
|
@@ -107,6 +113,8 @@ from utilities.typing import (
|
|
107
113
|
is_mapping_type,
|
108
114
|
is_namedtuple_class,
|
109
115
|
is_namedtuple_instance,
|
116
|
+
is_not_required_annotation,
|
117
|
+
is_not_required_type,
|
110
118
|
is_optional_type,
|
111
119
|
is_sequence_of,
|
112
120
|
is_sequence_of_tuple_or_str_mapping,
|
@@ -158,6 +166,13 @@ class TestGetArgs:
|
|
158
166
|
assert result == expected
|
159
167
|
|
160
168
|
|
169
|
+
class TestGetForwardRefArgs:
|
170
|
+
def test_main(self) -> None:
|
171
|
+
args = get_forward_ref_args(TypedDictFutureIntFloat)
|
172
|
+
expected = {"int_": "int", "float_": "float"}
|
173
|
+
assert args == expected
|
174
|
+
|
175
|
+
|
161
176
|
type _PlusOrMinusOneLit = Literal[1, -1]
|
162
177
|
type _TruthLit = Literal["true", "false"]
|
163
178
|
type _True = Literal["true"]
|
@@ -495,13 +510,23 @@ class TestGetTypeHints:
|
|
495
510
|
expected = {"truth": TrueOrFalseFutureTypeLit}
|
496
511
|
assert hints == expected
|
497
512
|
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
float_: float
|
502
|
-
|
503
|
-
|
504
|
-
|
513
|
+
@mark.parametrize(
|
514
|
+
("obj", "expected"),
|
515
|
+
[
|
516
|
+
param(TypedDictNoFutureIntFloat, {"int_": int, "float_": float}),
|
517
|
+
param(TypedDictFutureIntFloat, {"int_": int, "float_": float}),
|
518
|
+
param(
|
519
|
+
TypedDictNoFutureIntFloatOptional,
|
520
|
+
{"int_": int, "float_": NotRequired[float]},
|
521
|
+
),
|
522
|
+
param(
|
523
|
+
TypedDictFutureIntFloatOptional,
|
524
|
+
{"int_": int, "float_": NotRequired[float]},
|
525
|
+
),
|
526
|
+
],
|
527
|
+
)
|
528
|
+
def test_typed_dict(self, *, obj: _TypedDictMeta, expected: StrMapping) -> None:
|
529
|
+
hints = get_type_hints(obj)
|
505
530
|
assert hints == expected
|
506
531
|
|
507
532
|
@given(data=data())
|
@@ -637,6 +662,8 @@ class TestIsAnnotationOfType:
|
|
637
662
|
param(is_mapping_type, list[int], False),
|
638
663
|
param(is_mapping_type, set[int], False),
|
639
664
|
param(is_mapping_type, tuple[int, int], False),
|
665
|
+
param(is_not_required_type, NotRequired, True),
|
666
|
+
param(is_not_required_type, NotRequired[int], True),
|
640
667
|
param(is_optional_type, Literal["a", "b", "c"] | None, True),
|
641
668
|
param(is_optional_type, Literal["a", "b", "c"], False),
|
642
669
|
param(is_optional_type, int | None, True),
|
@@ -824,8 +851,39 @@ class TestIsInstanceGen:
|
|
824
851
|
param({"int_": 0, "float_": 0.0, "extra": None}, True),
|
825
852
|
],
|
826
853
|
)
|
827
|
-
|
828
|
-
|
854
|
+
@mark.parametrize(
|
855
|
+
"cls", [param(TypedDictNoFutureIntFloat), param(TypedDictFutureIntFloat)]
|
856
|
+
)
|
857
|
+
def test_typed_dict(self, *, obj: Any, cls: _TypedDictMeta, expected: bool) -> None:
|
858
|
+
result = is_instance_gen(obj, cls)
|
859
|
+
assert result is expected
|
860
|
+
|
861
|
+
@mark.parametrize(
|
862
|
+
("obj", "expected"),
|
863
|
+
[
|
864
|
+
param(None, False),
|
865
|
+
param({}, False),
|
866
|
+
param({None: False}, False),
|
867
|
+
param({"int_": None}, False),
|
868
|
+
param({"int_": 0}, True),
|
869
|
+
param({"int_": None, "float_": None}, False),
|
870
|
+
param({"int_": 0, "float_": None}, True),
|
871
|
+
param({"int_": None, "float_": 0.0}, False),
|
872
|
+
param({"int_": 0, "float_": 0.0}, True),
|
873
|
+
param({"int_": 0, "float_": 0.0, "extra": None}, True),
|
874
|
+
],
|
875
|
+
)
|
876
|
+
@mark.parametrize(
|
877
|
+
"cls",
|
878
|
+
[
|
879
|
+
param(TypedDictNoFutureIntFloatOptional),
|
880
|
+
param(TypedDictFutureIntFloatOptional),
|
881
|
+
],
|
882
|
+
)
|
883
|
+
def test_typed_dict_optional(
|
884
|
+
self, *, obj: Any, cls: _TypedDictMeta, expected: bool
|
885
|
+
) -> None:
|
886
|
+
result = is_instance_gen(obj, cls)
|
829
887
|
assert result is expected
|
830
888
|
|
831
889
|
def test_error(self) -> None:
|
@@ -884,6 +942,27 @@ class TestIsNamedTuple:
|
|
884
942
|
assert not is_namedtuple_instance(Example(x=0))
|
885
943
|
|
886
944
|
|
945
|
+
class TestIsNotRequiredAnnotation:
|
946
|
+
@mark.parametrize(
|
947
|
+
("obj", "expected"),
|
948
|
+
[
|
949
|
+
param(NotRequired, True),
|
950
|
+
param(NotRequired[int], True),
|
951
|
+
param(int, False),
|
952
|
+
param("NotRequired", True),
|
953
|
+
param("NotRequired[int]", True),
|
954
|
+
param("int", False),
|
955
|
+
param(ForwardRef("NotRequired"), True),
|
956
|
+
param(ForwardRef("NotRequired[int]"), True),
|
957
|
+
param(ForwardRef("int"), False),
|
958
|
+
param(None, False),
|
959
|
+
],
|
960
|
+
)
|
961
|
+
def test_main(self, *, obj: Any, expected: bool) -> None:
|
962
|
+
result = is_not_required_annotation(obj)
|
963
|
+
assert result is expected
|
964
|
+
|
965
|
+
|
887
966
|
class TestIsSequenceOf:
|
888
967
|
@mark.parametrize(
|
889
968
|
("obj", "expected"),
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
|
-
from typing import Literal
|
2
|
+
from typing import Literal, NotRequired, TypedDict
|
3
3
|
|
4
4
|
TrueOrFalseNoFutureLit = Literal["true", "false"]
|
5
5
|
type TrueOrFalseNoFutureTypeLit = Literal["true", "false"]
|
@@ -33,3 +33,13 @@ class DataClassNoFutureNestedOuterFirstOuter:
|
|
33
33
|
@dataclass(kw_only=True)
|
34
34
|
class DataClassNoFutureNestedOuterFirstInner:
|
35
35
|
int_: int
|
36
|
+
|
37
|
+
|
38
|
+
class TypedDictNoFutureIntFloat(TypedDict):
|
39
|
+
int_: int
|
40
|
+
float_: float
|
41
|
+
|
42
|
+
|
43
|
+
class TypedDictNoFutureIntFloatOptional(TypedDict):
|
44
|
+
int_: int
|
45
|
+
float_: NotRequired[float]
|
{dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/test_typing_funcs/with_future.py
RENAMED
@@ -1,7 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from dataclasses import dataclass, field
|
4
|
-
from typing import TYPE_CHECKING, Literal, TypedDict, override
|
4
|
+
from typing import TYPE_CHECKING, Literal, NotRequired, TypedDict, override
|
5
5
|
|
6
6
|
if TYPE_CHECKING:
|
7
7
|
from pathlib import Path
|
@@ -239,3 +239,8 @@ class DataClassFutureZonedDateTimePeriod:
|
|
239
239
|
class TypedDictFutureIntFloat(TypedDict):
|
240
240
|
int_: int
|
241
241
|
float_: float
|
242
|
+
|
243
|
+
|
244
|
+
class TypedDictFutureIntFloatOptional(TypedDict):
|
245
|
+
int_: int
|
246
|
+
float_: NotRequired[float]
|
@@ -105,6 +105,7 @@ from utilities.whenever import (
|
|
105
105
|
from utilities.zoneinfo import UTC, to_time_zone_name
|
106
106
|
|
107
107
|
if TYPE_CHECKING:
|
108
|
+
import datetime as dt
|
108
109
|
from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
|
109
110
|
from collections.abc import Set as AbstractSet
|
110
111
|
|
@@ -2460,6 +2461,34 @@ class RoundToFloatError(Exception):
|
|
2460
2461
|
##
|
2461
2462
|
|
2462
2463
|
|
2464
|
+
def search_period(
|
2465
|
+
series: Series,
|
2466
|
+
date_time: ZonedDateTime,
|
2467
|
+
/,
|
2468
|
+
*,
|
2469
|
+
start_or_end: Literal["start", "end"] = "end",
|
2470
|
+
) -> int | None:
|
2471
|
+
"""Search a series of periods for the one containing a given date-time."""
|
2472
|
+
start, end = [series.struct[k] for k in ["start", "end"]]
|
2473
|
+
py_date_time = date_time.py_datetime()
|
2474
|
+
match start_or_end:
|
2475
|
+
case "start":
|
2476
|
+
index = end.search_sorted(py_date_time, side="right")
|
2477
|
+
if index >= len(series):
|
2478
|
+
return None
|
2479
|
+
item: dt.datetime = series[index]["start"]
|
2480
|
+
return index if py_date_time >= item else None
|
2481
|
+
case "end":
|
2482
|
+
index = end.search_sorted(py_date_time, side="left")
|
2483
|
+
if index >= len(series):
|
2484
|
+
return None
|
2485
|
+
item: dt.datetime = series[index]["start"]
|
2486
|
+
return index if py_date_time > item else None
|
2487
|
+
|
2488
|
+
|
2489
|
+
##
|
2490
|
+
|
2491
|
+
|
2463
2492
|
def select_exact(
|
2464
2493
|
df: DataFrame, /, *columns: IntoExprColumn, drop: MaybeIterable[str] | None = None
|
2465
2494
|
) -> DataFrame:
|
@@ -2750,6 +2779,7 @@ __all__ = [
|
|
2750
2779
|
"read_series",
|
2751
2780
|
"replace_time_zone",
|
2752
2781
|
"round_to_float",
|
2782
|
+
"search_period",
|
2753
2783
|
"select_exact",
|
2754
2784
|
"serialize_dataframe",
|
2755
2785
|
"set_first_row_as_columns",
|
@@ -6,12 +6,14 @@ from dataclasses import dataclass, is_dataclass
|
|
6
6
|
from functools import partial
|
7
7
|
from itertools import chain
|
8
8
|
from pathlib import Path
|
9
|
+
from re import search
|
9
10
|
from types import NoneType, UnionType
|
10
11
|
from typing import (
|
11
12
|
Any,
|
12
13
|
ForwardRef,
|
13
14
|
Literal,
|
14
15
|
NamedTuple,
|
16
|
+
NotRequired,
|
15
17
|
Optional, # pyright: ignore[reportDeprecated]
|
16
18
|
TypeAliasType,
|
17
19
|
TypeGuard,
|
@@ -56,6 +58,18 @@ def get_args(obj: Any, /, *, optional_drop_none: bool = False) -> tuple[Any, ...
|
|
56
58
|
##
|
57
59
|
|
58
60
|
|
61
|
+
def get_forward_ref_args(obj: Any, /) -> Mapping[str, str]:
|
62
|
+
"""Get the forward args."""
|
63
|
+
return {
|
64
|
+
k: v.__forward_arg__
|
65
|
+
for k, v in obj.__annotations__.items()
|
66
|
+
if isinstance(v, ForwardRef)
|
67
|
+
}
|
68
|
+
|
69
|
+
|
70
|
+
##
|
71
|
+
|
72
|
+
|
59
73
|
def get_literal_elements(obj: Any, /) -> list[Any]:
|
60
74
|
"""Get the elements of a literal annotation."""
|
61
75
|
return _get_literal_elements_inner(obj)
|
@@ -151,21 +165,20 @@ def get_type_hints(
|
|
151
165
|
globalns_use = globals() | ({} if globalns is None else dict(globalns))
|
152
166
|
localns_use = {} if localns is None else dict(localns)
|
153
167
|
result: dict[str, Any] = obj.__annotations__
|
154
|
-
result =
|
155
|
-
k: v.__forward_arg__ if isinstance(v, ForwardRef) else v
|
156
|
-
for k, v in result.items()
|
157
|
-
}
|
168
|
+
result = result | dict(get_forward_ref_args(obj))
|
158
169
|
try:
|
159
|
-
hints = _get_type_hints(
|
170
|
+
hints = _get_type_hints(
|
171
|
+
obj, globalns=globalns_use, localns=localns_use, include_extras=True
|
172
|
+
)
|
160
173
|
except NameError as error:
|
161
174
|
if warn_name_errors:
|
162
175
|
warn(f"Error getting type hints for {obj!r}; {error}", stacklevel=2)
|
163
176
|
else:
|
164
|
-
result
|
177
|
+
result = result | {
|
165
178
|
key: value
|
166
179
|
for key, value in hints.items()
|
167
180
|
if (key not in result) or isinstance(result[key], str)
|
168
|
-
}
|
181
|
+
}
|
169
182
|
return result
|
170
183
|
|
171
184
|
|
@@ -393,17 +406,21 @@ def _is_instance_typed_dict[T: _TypedDictMeta](
|
|
393
406
|
hints = get_type_hints(
|
394
407
|
type_, globalns=globalns, localns=localns, warn_name_errors=warn_name_errors
|
395
408
|
)
|
396
|
-
|
409
|
+
optional = {
|
410
|
+
k for k, v in type_.__annotations__.items() if is_not_required_annotation(v)
|
411
|
+
}
|
412
|
+
required = {k: v for k, v in hints.items() if k not in optional}
|
413
|
+
if not set(obj).issuperset(required):
|
397
414
|
return False
|
398
415
|
return all(
|
399
416
|
is_instance_gen(
|
400
417
|
obj[k],
|
401
|
-
|
418
|
+
required[k],
|
402
419
|
globalns=globalns,
|
403
420
|
localns=localns,
|
404
421
|
warn_name_errors=warn_name_errors,
|
405
422
|
)
|
406
|
-
for k in
|
423
|
+
for k in required
|
407
424
|
)
|
408
425
|
|
409
426
|
|
@@ -577,6 +594,30 @@ def _is_namedtuple_core(obj: Any, /) -> bool:
|
|
577
594
|
##
|
578
595
|
|
579
596
|
|
597
|
+
def is_not_required_annotation(obj: Any) -> bool:
|
598
|
+
"""Check if an annotation is not required."""
|
599
|
+
if is_not_required_type(obj):
|
600
|
+
return True
|
601
|
+
match obj:
|
602
|
+
case str() as text:
|
603
|
+
return bool(search("NotRequired", text))
|
604
|
+
case ForwardRef() as fr:
|
605
|
+
return is_not_required_annotation(fr.__forward_arg__)
|
606
|
+
case _:
|
607
|
+
return False
|
608
|
+
|
609
|
+
|
610
|
+
##
|
611
|
+
|
612
|
+
|
613
|
+
def is_not_required_type(obj: Any, /) -> bool:
|
614
|
+
"""Check if an object is a not-required type annotation."""
|
615
|
+
return (obj is NotRequired) or _is_annotation_of_type(obj, NotRequired)
|
616
|
+
|
617
|
+
|
618
|
+
##
|
619
|
+
|
620
|
+
|
580
621
|
def is_optional_type(obj: Any, /) -> bool:
|
581
622
|
"""Check if an object is an optional type annotation."""
|
582
623
|
is_optional = _is_annotation_of_type(obj, Optional) # pyright: ignore[reportDeprecated]
|
@@ -889,6 +930,8 @@ __all__ = [
|
|
889
930
|
"is_mapping_type",
|
890
931
|
"is_namedtuple_class",
|
891
932
|
"is_namedtuple_instance",
|
933
|
+
"is_not_required_annotation",
|
934
|
+
"is_not_required_type",
|
892
935
|
"is_optional_type",
|
893
936
|
"is_sequence_of",
|
894
937
|
"is_sequence_of_tuple_or_str_mapping",
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_missing/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_missing/module.py
RENAMED
File without changes
|
{dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_with/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_without/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/src/tests/modules/package_without/module_1.py
RENAMED
File without changes
|
{dycw_utilities-0.165.1 → dycw_utilities-0.165.3}/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
|
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
|