diff --git a/README.ipynb b/README.ipynb index 8701f08..ef25721 100644 --- a/README.ipynb +++ b/README.ipynb @@ -26,7 +26,10 @@ "\n", "from IPython.display import Markdown as md\n", "\n", - "def flink(title: str, name: str):\n", + "def flink(title: str, name: str=None):\n", + " # name is method name\n", + " if name is None:\n", + " name = title.replace('`', '') # meh\n", " split = name.split('.', maxsplit=1)\n", " if len(split) == 1:\n", " modname = split[0]\n", @@ -50,6 +53,7 @@ "dmd = lambda x: display(md(x))\n", "\n", "import cachew\n", + "import cachew.experimental\n", "import cachew.tests.test_cachew as tests" ] }, @@ -246,6 +250,9 @@ " * {flink('Optional', 'tests.test_optional')} types\n", " * {flink('Union', 'tests.test_union')} types\n", " * {flink('nested datatypes', 'tests.test_nested')}\n", + " * {flink('Exceptions', 'tests.test_exceptions')} (experimental, enabled by calling {flink('`cachew.experimental.enable_exceptions`')})\n", + " {cachew.experimental.enable_exceptions.__doc__.replace(' ', ' ' * 7)}\n", + " \n", "* detects {flink('datatype schema changes', 'tests.test_schema_change')} and discards old data automatically \n", "\"\"\")\n", "# * custom hash function TODO example with mtime?" diff --git a/README.md b/README.md index eaddbc4..0100c9b 100644 --- a/README.md +++ b/README.md @@ -119,10 +119,10 @@ Cachew gives me best of two worlds and makes it **easy and efficient**. Only thi # How it works -Basically, your data objects get [flattened out](src/cachew/__init__.py#L350) -and python types are mapped [onto sqlite types and back](src/cachew/__init__.py#L420). +Basically, your data objects get [flattened out](src/cachew/__init__.py#L356) +and python types are mapped [onto sqlite types and back](src/cachew/__init__.py#L426). -When the function is called, cachew [computes the hash of your function's arguments ](src/cachew/__init__.py:#L674) +When the function is called, cachew [computes the hash of your function's arguments ](src/cachew/__init__.py:#L690) and compares it against the previously stored hash value. - If they match, it would deserialize and yield whatever is stored in the cache database @@ -141,8 +141,17 @@ and compares it against the previously stored hash value. * primitive: `str`, `int`, `float`, `bool`, `datetime`, `date`, `dict` * [Optional](src/cachew/tests/test_cachew.py#L340) types - * [Union](src/cachew/tests/test_cachew.py#L518) types + * [Union](src/cachew/tests/test_cachew.py#L521) types * [nested datatypes](src/cachew/tests/test_cachew.py#L256) + * [Exceptions](src/cachew/tests/test_cachew.py#L644) (experimental, enabled by calling [`cachew.experimental.enable_exceptions`](src/cachew/__init__.py#L28)) + + Enables support for caching Exceptions. Exception arguments are going to be serialized as strings. + + It's useful for defensive error handling, in case of cachew in particular for preserving error state. + + I elaborate on it here: [mypy-driven error handling](https://beepb00p.xyz/mypy-error-handling.html#kiss). + + * detects [datatype schema changes](src/cachew/tests/test_cachew.py#L286) and discards old data automatically @@ -157,7 +166,7 @@ I haven't set up formal benchmarking/regression tests yet, so don't want to make # Using -See [docstring](src/cachew/__init__.py#L573) for up-to-date documentation on parameters and return types. +See [docstring](src/cachew/__init__.py#L588) for up-to-date documentation on parameters and return types. You can also use [extensive unit tests](src/cachew/tests/test_cachew.py) as a reference. Some useful arguments of `@cachew` decorator: diff --git a/src/cachew/experimental.py b/src/cachew/experimental.py index c96a3eb..c3f55dc 100644 --- a/src/cachew/experimental.py +++ b/src/cachew/experimental.py @@ -26,6 +26,13 @@ def process_result_value(self, value: Optional[str], dialect) -> Optional[Except def enable_exceptions(): + """ + Enables support for caching Exceptions. Exception arguments are going to be serialized as strings. + + It's useful for defensive error handling, in case of cachew in particular for preserving error state. + + I elaborate on it here: [mypy-driven error handling](https://beepb00p.xyz/mypy-error-handling.html#kiss). + """ if Exception not in PRIMITIVES: PRIMITIVES[Exception] = ExceptionAdapter diff --git a/src/cachew/tests/test_cachew.py b/src/cachew/tests/test_cachew.py index 5b723bc..d9fcdb2 100644 --- a/src/cachew/tests/test_cachew.py +++ b/src/cachew/tests/test_cachew.py @@ -449,7 +449,9 @@ class Test: a_dt : datetime a_date : date a_json : Dict[str, Any] - a_exc : Optional[Exception] # TODO ugh. exceptions can't be compared really... + + # temporary commented: experimental feature + # a_exc : Optional[Exception] # TODO ugh. exceptions can't be compared really... # pylint: disable=no-member assert len(Test.__annotations__) == len(PRIMITIVES) # precondition so we don't forget to update test @@ -462,7 +464,6 @@ class Test: a_dt =datetime.now(tz=tz), a_date =datetime.now().replace(year=2000).date(), a_json ={'a': True, 'x': {'whatever': 3.14}}, - a_exc=None, ) @cachew(tdir)