|
16 | 16 | }, |
17 | 17 | "outputs": [], |
18 | 18 | "source": [ |
19 | | - "from pathlib import Path\n", |
20 | | - "import sys; sys.path.insert(0, str(Path('src').absolute()))\n", |
21 | | - "import os\n", |
22 | | - "cwd =os.getcwd()\n", |
| 19 | + "from __future__ import annotations\n", |
23 | 20 | "\n", |
24 | 21 | "import ast\n", |
25 | 22 | "import inspect\n", |
| 23 | + "import sys\n", |
| 24 | + "from pathlib import Path\n", |
26 | 25 | "\n", |
27 | 26 | "from IPython.display import Markdown as md\n", |
28 | 27 | "\n", |
29 | | - "def flink(title: str, name: str=None):\n", |
| 28 | + "##\n", |
| 29 | + "sys.path.insert(0, str(Path('src').absolute()))\n", |
| 30 | + "import cachew # isort: skip\n", |
| 31 | + "import cachew.extra # isort: skip\n", |
| 32 | + "import cachew.marshall.cachew # isort: skip\n", |
| 33 | + "import cachew.tests.test_cachew as tests # isort: skip\n", |
| 34 | + "sys.modules['tests'] = tests # meh\n", |
| 35 | + "##\n", |
| 36 | + "\n", |
| 37 | + "_CWD = Path.cwd()\n", |
| 38 | + "\n", |
| 39 | + "\n", |
| 40 | + "def flink(title: str, name: str | None = None) -> str:\n", |
30 | 41 | " # name is method name\n", |
31 | 42 | " if name is None:\n", |
32 | | - " name = title.replace('`', '') # meh\n", |
| 43 | + " name = title.replace('`', '') # meh\n", |
33 | 44 | " split = name.rsplit('.', maxsplit=1)\n", |
34 | 45 | " if len(split) == 1:\n", |
35 | 46 | " modname = split[0]\n", |
|
38 | 49 | " [modname, fname] = split\n", |
39 | 50 | " module = sys.modules[modname]\n", |
40 | 51 | "\n", |
41 | | - " file = Path(module.__file__).relative_to(cwd)\n", |
| 52 | + " file = Path(module.__file__).relative_to(_CWD)\n", |
42 | 53 | "\n", |
43 | 54 | " if fname is not None:\n", |
44 | 55 | " func = module\n", |
|
50 | 61 | " numbers = ''\n", |
51 | 62 | " return f'[{title}]({file}{numbers})'\n", |
52 | 63 | "\n", |
53 | | - "dmd = lambda x: display(md(x.strip()))\n", |
54 | 64 | "\n", |
55 | | - "import cachew\n", |
56 | | - "import cachew.extra\n", |
57 | | - "import cachew.marshall.cachew\n", |
58 | | - "import cachew.tests.test_cachew as tests\n", |
59 | | - "sys.modules['tests'] = tests # meh" |
| 65 | + "dmd = lambda x: display(md(x.strip()))" |
60 | 66 | ] |
61 | 67 | }, |
62 | 68 | { |
|
72 | 78 | }, |
73 | 79 | "outputs": [], |
74 | 80 | "source": [ |
75 | | - "dmd(f'''\n", |
| 81 | + "dmd('''\n", |
76 | 82 | "<!--\n", |
77 | 83 | "THIS FILE IS AUTOGENERATED BY README.ipynb.\n", |
78 | | - "Ideally you should edit README.ipynb and use 'generate-readme' to produce README.md. \n", |
| 84 | + "Ideally you should edit README.ipynb and use 'generate-readme' to produce README.md.\n", |
79 | 85 | "But it's okay to edit README.md too directly if you want to fix something -- I can run generate-readme myself later.\n", |
80 | 86 | "-->\n", |
81 | 87 | "''')" |
|
221 | 227 | "outputs": [], |
222 | 228 | "source": [ |
223 | 229 | "[composite] = [x\n", |
224 | | - " for x in ast.walk(ast.parse(inspect.getsource(cachew))) \n", |
| 230 | + " for x in ast.walk(ast.parse(inspect.getsource(cachew)))\n", |
225 | 231 | " if isinstance(x, ast.FunctionDef) and x.name == 'composite_hash'\n", |
226 | 232 | "]\n", |
227 | 233 | "\n", |
228 | | - "link = f'{Path(cachew.__file__).relative_to(cwd)}:#L{composite.lineno}'\n", |
| 234 | + "link = f'{Path(cachew.__file__).relative_to(_CWD)}:#L{composite.lineno}'\n", |
229 | 235 | "\n", |
230 | 236 | "dmd(f'''\n", |
231 | 237 | "# How it works\n", |
232 | 238 | "\n", |
233 | | - "- first your objects get {flink('converted', 'cachew.marshall.cachew.CachewMarshall')} into a simpler JSON-like representation \n", |
| 239 | + "- first your objects get {flink('converted', 'cachew.marshall.cachew.CachewMarshall')} into a simpler JSON-like representation\n", |
234 | 240 | "- after that, they are mapped into byte blobs via [`orjson`](https://github.com/ijl/orjson).\n", |
235 | 241 | "\n", |
236 | 242 | "When the function is called, cachew [computes the hash of your function's arguments ]({link})\n", |
237 | 243 | "and compares it against the previously stored hash value.\n", |
238 | | - " \n", |
| 244 | + "\n", |
239 | 245 | "- If they match, it would deserialize and yield whatever is stored in the cache database\n", |
240 | 246 | "- If the hash mismatches, the original function is called and new data is stored along with the new hash\n", |
241 | 247 | "''')" |
|
258 | 264 | "types = [f'`{t}`' for t in ['str', 'int', 'float', 'bool', 'datetime', 'date', 'Exception']]\n", |
259 | 265 | "dmd(f\"\"\"\n", |
260 | 266 | "* automatic schema inference: {flink('1', 'tests.test_return_type_inference')}, {flink('2', 'tests.test_return_type_mismatch')}\n", |
261 | | - "* supported types: \n", |
| 267 | + "* supported types:\n", |
262 | 268 | "\n", |
263 | 269 | " * primitive: {', '.join(types)}\n", |
264 | | - " \n", |
| 270 | + "\n", |
265 | 271 | " See {flink('tests.test_types')}, {flink('tests.test_primitive')}, {flink('tests.test_dates')}, {flink('tests.test_exceptions')}\n", |
266 | 272 | " * {flink('@dataclass and NamedTuple', 'tests.test_dataclass')}\n", |
267 | 273 | " * {flink('Optional', 'tests.test_optional')} types\n", |
268 | 274 | " * {flink('Union', 'tests.test_union')} types\n", |
269 | 275 | " * {flink('nested datatypes', 'tests.test_nested')}\n", |
270 | | - " \n", |
271 | | - "* detects {flink('datatype schema changes', 'tests.test_schema_change')} and discards old data automatically \n", |
| 276 | + "\n", |
| 277 | + "* detects {flink('datatype schema changes', 'tests.test_schema_change')} and discards old data automatically\n", |
272 | 278 | "\"\"\")\n", |
273 | 279 | "# * custom hash function TODO example with mtime?" |
274 | 280 | ] |
|
302 | 308 | "source": [ |
303 | 309 | "dmd(f\"\"\"\n", |
304 | 310 | "# Using\n", |
305 | | - "See {flink('docstring', 'cachew.cachew')} for up-to-date documentation on parameters and return types. \n", |
| 311 | + "See {flink('docstring', 'cachew.cachew')} for up-to-date documentation on parameters and return types.\n", |
306 | 312 | "You can also use {flink('extensive unit tests', 'tests')} as a reference.\n", |
307 | | - " \n", |
| 313 | + "\n", |
308 | 314 | "Some useful (but optional) arguments of `@cachew` decorator:\n", |
309 | | - " \n", |
| 315 | + "\n", |
310 | 316 | "* `cache_path` can be a directory, or a callable that {flink('returns a path', 'tests.test_callable_cache_path')} and depends on function's arguments.\n", |
311 | | - " \n", |
| 317 | + "\n", |
312 | 318 | " By default, `settings.DEFAULT_CACHEW_DIR` is used.\n", |
313 | | - " \n", |
| 319 | + "\n", |
314 | 320 | "* `depends_on` is a function which determines whether your inputs have changed, and the cache needs to be invalidated.\n", |
315 | | - " \n", |
| 321 | + "\n", |
316 | 322 | " By default it just uses string representation of the arguments, you can also specify a custom callable.\n", |
317 | | - " \n", |
| 323 | + "\n", |
318 | 324 | " For instance, it can be used to {flink('discard cache', 'tests.test_custom_hash')} if the input file was modified.\n", |
319 | | - " \n", |
| 325 | + "\n", |
320 | 326 | "* `cls` is the type that would be serialized.\n", |
321 | 327 | "\n", |
322 | | - " By default, it is inferred from return type annotations, but can be specified explicitly if you don't control the code you want to cache. \n", |
| 328 | + " By default, it is inferred from return type annotations, but can be specified explicitly if you don't control the code you want to cache.\n", |
323 | 329 | "\"\"\")" |
324 | 330 | ] |
325 | 331 | }, |
|
415 | 421 | "outputs": [], |
416 | 422 | "source": [ |
417 | 423 | "import cachew.extra\n", |
| 424 | + "\n", |
418 | 425 | "dmd(f\"\"\"```python\n", |
419 | 426 | "{inspect.getsource(cachew.extra.mcachew)}\n", |
420 | 427 | "```\"\"\")" |
|
442 | 449 | "- `DEFAULT_CACHEW_DIR`: override to set a different base directory. The default is the \"user cache directory\" (see [platformdirs docs](https://github.com/tox-dev/platformdirs?tab=readme-ov-file#example-output)).\n", |
443 | 450 | "- `THROW_ON_ERROR`: by default, cachew is defensive and simply attemps to cause the original function on caching issues.\n", |
444 | 451 | " Set to `True` to catch errors earlier.\n", |
445 | | - "- `DEFAULT_BACKEND`: currently supported are `sqlite` and `file` (file is somewhat experimental, although should work too). \n", |
| 452 | + "- `DEFAULT_BACKEND`: currently supported are `sqlite` and `file` (file is somewhat experimental, although should work too).\n", |
446 | 453 | "\n", |
447 | 454 | "''')" |
448 | 455 | ] |
|
0 commit comments