dycw-utilities 0.153.6__tar.gz → 0.153.8__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.153.6 → dycw_utilities-0.153.8}/PKG-INFO +1 -1
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/pyproject.toml +2 -2
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/conftest.py +46 -27
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_functions.py +45 -17
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_sqlalchemy.py +34 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/__init__.py +1 -1
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/functions.py +16 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/sqlalchemy.py +25 -3
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/.gitignore +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/LICENSE +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/README.md +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/__init__.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/__init__.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_missing/__init__.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_missing/module.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_with/__init__.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_with/outer_1.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_with/outer_2.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_without/__init__.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_without/module_1.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_without/module_2.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/standalone.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/with_imports.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_altair.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_asyncio.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_atomicwrites.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_atools.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_cachetools.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_click.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_concurrent.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_contextlib.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_contextvars.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_cryptography.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_cvxpy.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_dataclasses.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_enum.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_errors.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_eventkit.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_fastapi.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_fpdf2.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_functools.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_getpass.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_gzip.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_hashlib.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_http.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_hypothesis.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_importlib.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_inflect.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_ipython.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_iterables.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_json.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_jupyter.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_libcst.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_lightweight_charts.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_logging.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_math.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_memory_profiler.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_modules.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_more_itertools.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_numpy.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_objects/__init__.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_objects/objects.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_operator.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_optuna.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_orjson.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_os.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_parse.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_pathlib.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_pickle.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_platform.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_polars.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_polars_ols.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_postgres.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_pottery.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_pqdm.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_psutil.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_pyinstrument.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_pytest.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_pytest_randomly.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_pytest_regressions.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_random.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_re.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_redis.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_reprlib.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_scipy.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_sentinel.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_shelve.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_slack_sdk.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_socket.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_statsmodels.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_string.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_tempfile.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_text.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_threading.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_timer.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_traceback.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_typed_settings.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_types.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_typing.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_typing_funcs/__init__.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_typing_funcs/no_future.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_typing_funcs/with_future.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_tzdata.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_tzlocal.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_uuid.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_version.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_warnings.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_whenever.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_yield_access/__init__.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_yield_access/script.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_yield_access/script.sh +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_zipfile.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/test_zoneinfo.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/altair.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/asyncio.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/atomicwrites.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/atools.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/cachetools.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/click.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/concurrent.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/contextlib.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/contextvars.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/cryptography.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/cvxpy.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/dataclasses.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/enum.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/errors.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/eventkit.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/fastapi.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/fpdf2.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/functools.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/getpass.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/gzip.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/hashlib.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/http.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/hypothesis.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/importlib.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/inflect.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/ipython.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/iterables.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/json.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/jupyter.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/libcst.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/lightweight_charts.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/logging.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/math.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/memory_profiler.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/modules.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/more_itertools.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/numpy.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/operator.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/optuna.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/orjson.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/os.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/parse.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/pathlib.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/pickle.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/platform.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/polars.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/polars_ols.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/postgres.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/pottery.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/pqdm.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/psutil.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/py.typed +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/pyinstrument.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/pytest.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/pytest_plugins/__init__.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/pytest_plugins/pytest_randomly.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/pytest_plugins/pytest_regressions.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/pytest_regressions.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/random.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/re.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/redis.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/reprlib.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/scipy.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/sentinel.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/shelve.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/slack_sdk.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/socket.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/sqlalchemy_polars.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/statsmodels.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/string.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/tempfile.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/text.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/threading.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/timer.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/traceback.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/typed_settings.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/types.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/typing.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/tzdata.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/tzlocal.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/uuid.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/version.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/warnings.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/whenever.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/zipfile.py +0 -0
- {dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/utilities/zoneinfo.py +0 -0
@@ -229,7 +229,7 @@ dependencies = [
|
|
229
229
|
name = "dycw-utilities"
|
230
230
|
readme = "README.md"
|
231
231
|
requires-python = ">= 3.12"
|
232
|
-
version = "0.153.
|
232
|
+
version = "0.153.8"
|
233
233
|
|
234
234
|
[project.entry-points.pytest11]
|
235
235
|
pytest-randomly = "utilities.pytest_plugins.pytest_randomly"
|
@@ -262,7 +262,7 @@ test = [
|
|
262
262
|
# bump-my-version
|
263
263
|
[tool.bumpversion]
|
264
264
|
allow_dirty = true
|
265
|
-
current_version = "0.153.
|
265
|
+
current_version = "0.153.8"
|
266
266
|
|
267
267
|
[[tool.bumpversion.files]]
|
268
268
|
filename = "src/utilities/__init__.py"
|
@@ -114,42 +114,61 @@ def test_engine(*, request: SubRequest, tmp_path: Path) -> Engine:
|
|
114
114
|
|
115
115
|
|
116
116
|
@fixture(params=[param("sqlite"), param("postgresql", marks=SKIPIF_CI)])
|
117
|
-
async def test_async_engine(
|
118
|
-
|
119
|
-
|
117
|
+
async def test_async_engine(
|
118
|
+
*,
|
119
|
+
request: SubRequest,
|
120
|
+
test_async_sqlite_engine: AsyncEngine,
|
121
|
+
test_async_postgres_engine: AsyncEngine,
|
122
|
+
) -> AsyncEngine:
|
120
123
|
dialect = request.param
|
121
124
|
match dialect:
|
122
125
|
case "sqlite":
|
123
|
-
|
124
|
-
return create_engine("sqlite+aiosqlite", database=str(db_path), async_=True)
|
126
|
+
return test_async_sqlite_engine
|
125
127
|
case "postgresql":
|
126
|
-
|
127
|
-
|
128
|
-
engine = create_engine(
|
129
|
-
"postgresql+asyncpg",
|
130
|
-
host="localhost",
|
131
|
-
port=5432,
|
132
|
-
database="testing",
|
133
|
-
async_=True,
|
134
|
-
)
|
135
|
-
try:
|
136
|
-
async with engine.begin() as conn:
|
137
|
-
tables: Sequence[str] = (
|
138
|
-
(await conn.execute(_select_tables())).scalars().all()
|
139
|
-
)
|
140
|
-
except InvalidCatalogNameError:
|
141
|
-
...
|
142
|
-
else:
|
143
|
-
for table in filter(_is_to_drop, tables):
|
144
|
-
async with engine.begin() as conn:
|
145
|
-
with suppress(Exception):
|
146
|
-
_ = await conn.execute(_drop_table(table))
|
147
|
-
return engine
|
128
|
+
return test_async_postgres_engine
|
148
129
|
case _:
|
149
130
|
msg = f"Unsupported dialect: {dialect}"
|
150
131
|
raise NotImplementedError(msg)
|
151
132
|
|
152
133
|
|
134
|
+
@fixture
|
135
|
+
async def test_async_sqlite_engine(*, tmp_path: Path) -> AsyncEngine:
|
136
|
+
from utilities.sqlalchemy import create_engine
|
137
|
+
|
138
|
+
db_path = tmp_path / "db.sqlite"
|
139
|
+
return create_engine("sqlite+aiosqlite", database=str(db_path), async_=True)
|
140
|
+
|
141
|
+
|
142
|
+
@fixture
|
143
|
+
async def test_async_postgres_engine() -> AsyncEngine:
|
144
|
+
from asyncpg.exceptions import InvalidCatalogNameError
|
145
|
+
|
146
|
+
from utilities.sqlalchemy import create_engine
|
147
|
+
|
148
|
+
if IS_CI:
|
149
|
+
skip(reason="Skipped for CI")
|
150
|
+
engine = create_engine(
|
151
|
+
"postgresql+asyncpg",
|
152
|
+
host="localhost",
|
153
|
+
port=5432,
|
154
|
+
database="testing",
|
155
|
+
async_=True,
|
156
|
+
)
|
157
|
+
try:
|
158
|
+
async with engine.begin() as conn:
|
159
|
+
tables: Sequence[str] = (
|
160
|
+
(await conn.execute(_select_tables())).scalars().all()
|
161
|
+
)
|
162
|
+
except InvalidCatalogNameError:
|
163
|
+
...
|
164
|
+
else:
|
165
|
+
for table in filter(_is_to_drop, tables):
|
166
|
+
async with engine.begin() as conn:
|
167
|
+
with suppress(Exception):
|
168
|
+
_ = await conn.execute(_drop_table(table))
|
169
|
+
return engine
|
170
|
+
|
171
|
+
|
153
172
|
def _is_to_drop(table: str, /) -> bool:
|
154
173
|
try:
|
155
174
|
datetime_str = extract_group(r"^(\d{8}T\d{6})_", table)
|
@@ -6,6 +6,8 @@ from functools import cache, cached_property, lru_cache, partial, wraps
|
|
6
6
|
from itertools import chain
|
7
7
|
from operator import neg
|
8
8
|
from pathlib import Path
|
9
|
+
from subprocess import check_output
|
10
|
+
from sys import executable
|
9
11
|
from types import NoneType
|
10
12
|
from typing import TYPE_CHECKING, Any, ClassVar, cast
|
11
13
|
|
@@ -22,7 +24,7 @@ from hypothesis.strategies import (
|
|
22
24
|
permutations,
|
23
25
|
sampled_from,
|
24
26
|
)
|
25
|
-
from pytest import raises
|
27
|
+
from pytest import mark, param, raises
|
26
28
|
|
27
29
|
from utilities.errors import ImpossibleCaseError
|
28
30
|
from utilities.functions import (
|
@@ -95,6 +97,7 @@ from utilities.functions import (
|
|
95
97
|
yield_object_properties,
|
96
98
|
)
|
97
99
|
from utilities.sentinel import sentinel
|
100
|
+
from utilities.text import parse_bool, strip_and_dedent
|
98
101
|
from utilities.whenever import NOW_UTC, ZERO_TIME, get_now, get_today
|
99
102
|
|
100
103
|
if TYPE_CHECKING:
|
@@ -131,40 +134,40 @@ class TestApplyDecorators:
|
|
131
134
|
assert counter == 1
|
132
135
|
|
133
136
|
|
134
|
-
class
|
135
|
-
@given(case=sampled_from([(
|
136
|
-
def test_main(self, *, case: tuple[
|
137
|
+
class TestEnsureBool:
|
138
|
+
@given(case=sampled_from([(True, False), (True, True), (None, True)]))
|
139
|
+
def test_main(self, *, case: tuple[bool | None, bool]) -> None:
|
137
140
|
obj, nullable = case
|
138
|
-
_ =
|
141
|
+
_ = ensure_bool(obj, nullable=nullable)
|
139
142
|
|
140
143
|
@given(
|
141
144
|
case=sampled_from([
|
142
|
-
(False, "Object '.*' of type '.*' must be a
|
143
|
-
(True, "Object '.*' of type '.*' must be a
|
145
|
+
(False, "Object '.*' of type '.*' must be a boolean"),
|
146
|
+
(True, "Object '.*' of type '.*' must be a boolean or None"),
|
144
147
|
])
|
145
148
|
)
|
146
149
|
def test_error(self, *, case: tuple[bool, str]) -> None:
|
147
150
|
nullable, match = case
|
148
|
-
with raises(
|
149
|
-
_ =
|
151
|
+
with raises(EnsureBoolError, match=match):
|
152
|
+
_ = ensure_bool(sentinel, nullable=nullable)
|
150
153
|
|
151
154
|
|
152
|
-
class
|
153
|
-
@given(case=sampled_from([(
|
154
|
-
def test_main(self, *, case: tuple[
|
155
|
+
class TestEnsureBytes:
|
156
|
+
@given(case=sampled_from([(b"", False), (b"", True), (None, True)]))
|
157
|
+
def test_main(self, *, case: tuple[bytes | None, bool]) -> None:
|
155
158
|
obj, nullable = case
|
156
|
-
_ =
|
159
|
+
_ = ensure_bytes(obj, nullable=nullable)
|
157
160
|
|
158
161
|
@given(
|
159
162
|
case=sampled_from([
|
160
|
-
(False, "Object '.*' of type '.*' must be a
|
161
|
-
(True, "Object '.*' of type '.*' must be a
|
163
|
+
(False, "Object '.*' of type '.*' must be a byte string"),
|
164
|
+
(True, "Object '.*' of type '.*' must be a byte string or None"),
|
162
165
|
])
|
163
166
|
)
|
164
167
|
def test_error(self, *, case: tuple[bool, str]) -> None:
|
165
168
|
nullable, match = case
|
166
|
-
with raises(
|
167
|
-
_ =
|
169
|
+
with raises(EnsureBytesError, match=match):
|
170
|
+
_ = ensure_bytes(sentinel, nullable=nullable)
|
168
171
|
|
169
172
|
|
170
173
|
class TestEnsureClass:
|
@@ -915,6 +918,31 @@ class TestSecond:
|
|
915
918
|
assert second(pair) == y
|
916
919
|
|
917
920
|
|
921
|
+
class TestSkipIfOptimize:
|
922
|
+
@mark.parametrize("optimize", [param(True), param(False)])
|
923
|
+
def test_main(self, *, optimize: bool) -> None:
|
924
|
+
code = strip_and_dedent("""
|
925
|
+
from utilities.functions import skip_if_optimize
|
926
|
+
|
927
|
+
is_run = False
|
928
|
+
|
929
|
+
@skip_if_optimize
|
930
|
+
def func() -> None:
|
931
|
+
global is_run
|
932
|
+
is_run = True
|
933
|
+
|
934
|
+
func()
|
935
|
+
print(is_run)
|
936
|
+
""")
|
937
|
+
|
938
|
+
args = [executable]
|
939
|
+
if optimize:
|
940
|
+
args.append("-O")
|
941
|
+
args.extend(["-c", code])
|
942
|
+
is_run = parse_bool(check_output(args, text=True))
|
943
|
+
assert is_run is not optimize
|
944
|
+
|
945
|
+
|
918
946
|
class TestYieldObjectAttributes:
|
919
947
|
@given(n=integers())
|
920
948
|
def test_main(self, *, n: int) -> None:
|
@@ -1,6 +1,8 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
from asyncio import sleep
|
3
4
|
from enum import Enum, StrEnum, auto
|
5
|
+
from getpass import getuser
|
4
6
|
from itertools import chain
|
5
7
|
from typing import TYPE_CHECKING, Any, Literal, cast, overload, override
|
6
8
|
from uuid import uuid4
|
@@ -29,6 +31,7 @@ from sqlalchemy.orm import (
|
|
29
31
|
relationship,
|
30
32
|
)
|
31
33
|
|
34
|
+
from tests.conftest import SKIPIF_CI
|
32
35
|
from utilities.hypothesis import int32s, pairs, urls
|
33
36
|
from utilities.iterables import one
|
34
37
|
from utilities.modules import is_installed
|
@@ -72,6 +75,8 @@ from utilities.sqlalchemy import (
|
|
72
75
|
columnwise_max,
|
73
76
|
columnwise_min,
|
74
77
|
create_engine,
|
78
|
+
ensure_database_created,
|
79
|
+
ensure_database_dropped,
|
75
80
|
ensure_tables_created,
|
76
81
|
ensure_tables_dropped,
|
77
82
|
enum_name,
|
@@ -253,6 +258,35 @@ class TestCreateEngine:
|
|
253
258
|
assert isinstance(engine, cls)
|
254
259
|
|
255
260
|
|
261
|
+
@SKIPIF_CI
|
262
|
+
class TestEnsureDatabaseCreatedAndDropped:
|
263
|
+
async def test_main(self) -> None:
|
264
|
+
url = URL.create(
|
265
|
+
"postgresql+asyncpg",
|
266
|
+
username=getuser(),
|
267
|
+
password="password", # noqa: S106
|
268
|
+
host="localhost",
|
269
|
+
port=5432,
|
270
|
+
database="postgres",
|
271
|
+
)
|
272
|
+
database = f"testing_{_table_names()}"
|
273
|
+
for _ in range(2):
|
274
|
+
await ensure_database_created(url, database)
|
275
|
+
await sleep(0.1)
|
276
|
+
for _ in range(2):
|
277
|
+
await ensure_database_dropped(url, database)
|
278
|
+
await sleep(0.1)
|
279
|
+
|
280
|
+
async def _run_test(
|
281
|
+
self, engine: AsyncEngine, table_or_orm: TableOrORMInstOrClass, /
|
282
|
+
) -> None:
|
283
|
+
for _ in range(2):
|
284
|
+
await ensure_tables_created(engine, table_or_orm)
|
285
|
+
sel = select(get_table(table_or_orm))
|
286
|
+
async with engine.begin() as conn:
|
287
|
+
_ = (await conn.execute(sel)).all()
|
288
|
+
|
289
|
+
|
256
290
|
class TestEnsureTablesCreated:
|
257
291
|
async def test_table(self, *, test_async_engine: AsyncEngine) -> None:
|
258
292
|
table = Table(
|
@@ -935,6 +935,21 @@ def second[U](pair: tuple[Any, U], /) -> U:
|
|
935
935
|
##
|
936
936
|
|
937
937
|
|
938
|
+
def skip_if_optimize[**P](func: Callable[P, None], /) -> Callable[P, None]:
|
939
|
+
"""Skip a function if we are in the optimized mode."""
|
940
|
+
if __debug__:
|
941
|
+
return func
|
942
|
+
|
943
|
+
@wraps(func)
|
944
|
+
def wrapped(*args: P.args, **kwargs: P.kwargs) -> None:
|
945
|
+
_ = (args, kwargs)
|
946
|
+
|
947
|
+
return wrapped
|
948
|
+
|
949
|
+
|
950
|
+
##
|
951
|
+
|
952
|
+
|
938
953
|
def yield_object_attributes(
|
939
954
|
obj: Any,
|
940
955
|
/,
|
@@ -1043,6 +1058,7 @@ __all__ = [
|
|
1043
1058
|
"min_nullable",
|
1044
1059
|
"not_func",
|
1045
1060
|
"second",
|
1061
|
+
"skip_if_optimize",
|
1046
1062
|
"yield_object_attributes",
|
1047
1063
|
"yield_object_cached_properties",
|
1048
1064
|
"yield_object_properties",
|
@@ -30,7 +30,6 @@ from typing import (
|
|
30
30
|
)
|
31
31
|
|
32
32
|
import sqlalchemy
|
33
|
-
import sqlalchemy.ext.asyncio
|
34
33
|
from sqlalchemy import (
|
35
34
|
URL,
|
36
35
|
Column,
|
@@ -63,7 +62,7 @@ from sqlalchemy.exc import (
|
|
63
62
|
OperationalError,
|
64
63
|
ProgrammingError,
|
65
64
|
)
|
66
|
-
from sqlalchemy.ext.asyncio import AsyncConnection, AsyncEngine
|
65
|
+
from sqlalchemy.ext.asyncio import AsyncConnection, AsyncEngine, create_async_engine
|
67
66
|
from sqlalchemy.orm import (
|
68
67
|
DeclarativeBase,
|
69
68
|
InstrumentedAttribute,
|
@@ -311,7 +310,7 @@ def create_engine(
|
|
311
310
|
case False:
|
312
311
|
return sqlalchemy.create_engine(url, poolclass=poolclass)
|
313
312
|
case True:
|
314
|
-
return
|
313
|
+
return create_async_engine(url, poolclass=poolclass)
|
315
314
|
case never:
|
316
315
|
assert_never(never)
|
317
316
|
|
@@ -319,6 +318,27 @@ def create_engine(
|
|
319
318
|
##
|
320
319
|
|
321
320
|
|
321
|
+
async def ensure_database_created(super_: URL, database: str, /) -> None:
|
322
|
+
"""Ensure a database is created."""
|
323
|
+
engine = create_async_engine(super_, isolation_level="AUTOCOMMIT")
|
324
|
+
async with engine.begin() as conn:
|
325
|
+
try:
|
326
|
+
_ = await conn.execute(text(f"CREATE DATABASE {database}"))
|
327
|
+
except (OperationalError, ProgrammingError) as error:
|
328
|
+
if not search('database ".*" already exists', ensure_str(one(error.args))):
|
329
|
+
raise
|
330
|
+
|
331
|
+
|
332
|
+
async def ensure_database_dropped(super_: URL, database: str, /) -> None:
|
333
|
+
"""Ensure a database is dropped."""
|
334
|
+
engine = create_async_engine(super_, isolation_level="AUTOCOMMIT")
|
335
|
+
async with engine.begin() as conn:
|
336
|
+
_ = await conn.execute(text(f"DROP DATABASE IF EXISTS {database}"))
|
337
|
+
|
338
|
+
|
339
|
+
##
|
340
|
+
|
341
|
+
|
322
342
|
async def ensure_tables_created(
|
323
343
|
engine: AsyncEngine,
|
324
344
|
/,
|
@@ -1284,6 +1304,8 @@ __all__ = [
|
|
1284
1304
|
"columnwise_max",
|
1285
1305
|
"columnwise_min",
|
1286
1306
|
"create_engine",
|
1307
|
+
"ensure_database_created",
|
1308
|
+
"ensure_database_dropped",
|
1287
1309
|
"ensure_tables_created",
|
1288
1310
|
"ensure_tables_dropped",
|
1289
1311
|
"enum_name",
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_missing/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_missing/module.py
RENAMED
File without changes
|
{dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/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.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_without/__init__.py
RENAMED
File without changes
|
{dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/src/tests/modules/package_without/module_1.py
RENAMED
File without changes
|
{dycw_utilities-0.153.6 → dycw_utilities-0.153.8}/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
|
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
|
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
|