diff --git a/README.ipynb b/README.ipynb index 05422b5..8701f08 100644 --- a/README.ipynb +++ b/README.ipynb @@ -366,6 +366,34 @@ " * https://marshmallow-annotations.readthedocs.io/en/latest/ext/namedtuple.html#namedtuple-type-api\n", " * https://pypi.org/project/marshmallow-dataclass" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tips and tricks\n", + "## Optional dependency\n", + "You can benefit from `cachew` even if you don't want to bloat your app's dependencies. Just use the following snippet:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import cachew.misc\n", + "dmd(f\"\"\"```python\n", + "{inspect.getsource(cachew.misc.mcachew)}\n", + "```\"\"\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now you can use `@mcachew` in place of `@cachew`, and be certain things don't break if `cachew` is missing." + ] } ], "metadata": { diff --git a/src/cachew/misc.py b/src/cachew/misc.py new file mode 100644 index 0000000..9510a83 --- /dev/null +++ b/src/cachew/misc.py @@ -0,0 +1,15 @@ +# TODO Ideally, needs doublewraps as well? +def mcachew(*args, **kwargs): + """ + Stands for 'Maybe cachew'. + Defensive wrapper around @cachew to make it an optional dependency. + """ + try: + import cachew + except ModuleNotFoundError: + import warnings + warnings.warn('cachew library not found. You might want to install it to speed things up. See https://github.com/karlicoss/cachew') + return lambda orig_func: orig_func + else: + return cachew.cachew(*args, **kwargs) + diff --git a/src/cachew/tests/test_cachew.py b/src/cachew/tests/test_cachew.py index aa2b7bd..a6980aa 100644 --- a/src/cachew/tests/test_cachew.py +++ b/src/cachew/tests/test_cachew.py @@ -614,3 +614,16 @@ def test_concurrent_reads(tmp_path: Path, fuzz_cachew_impl): # should be pretty instantaneous # if it takes more, most likely means that helper was called again assert taken < 5 + + +def test_mcachew(tmp_path: Path): + # TODO how to test for defensive behaviour? + from cachew.misc import mcachew + + @mcachew(cache_path=tmp_path / 'cache') + def func() -> Iterator[str]: + yield 'one' + yield 'two' + + assert list(func()) == ['one', 'two'] + assert list(func()) == ['one', 'two']