{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Extra Methods in Fleche\n", "\n", "When you decorate a function with `@fleche`, it's not just a cached version of the original function. It also gains several helper methods that allow you to interact with the cache and the function's metadata directly." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2026-03-20T00:49:50.843152Z", "iopub.status.busy": "2026-03-20T00:49:50.842978Z", "iopub.status.idle": "2026-03-20T00:49:51.354437Z", "shell.execute_reply": "2026-03-20T00:49:51.353593Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "No config file found. Using default memory cache.\n" ] } ], "source": [ "from fleche import fleche\n", "import time" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2026-03-20T00:49:51.356694Z", "iopub.status.busy": "2026-03-20T00:49:51.356308Z", "iopub.status.idle": "2026-03-20T00:49:51.360352Z", "shell.execute_reply": "2026-03-20T00:49:51.359366Z" } }, "outputs": [], "source": [ "@fleche\n", "def slow_add(a, b):\n", " \"\"\"Adds two numbers slowly.\"\"\"\n", " time.sleep(1)\n", " return a + b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. `.call(*args, **kwargs)`\n", "\n", "The `.call` method returns a `Call` object. This object captures all the information about a potential call to the function, including the function name, arguments, and metadata, without actually executing the function." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2026-03-20T00:49:51.362781Z", "iopub.status.busy": "2026-03-20T00:49:51.362549Z", "iopub.status.idle": "2026-03-20T00:49:51.367354Z", "shell.execute_reply": "2026-03-20T00:49:51.366291Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Function Name: slow_add\n", "Arguments: {'a': 10, 'b': 20}\n", "Call Object: Call(name='slow_add', arguments={'a': 10, 'b': 20}, metadata={}, module='__main__', version=None, code_digest=None, result=None)\n" ] } ], "source": [ "call_info = slow_add.call(10, b=20)\n", "print(f\"Function Name: {call_info.name}\")\n", "print(f\"Arguments: {call_info.arguments}\")\n", "print(f\"Call Object: {call_info}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. `.digest(*args, **kwargs)`\n", "\n", "The `.digest` method returns the unique cache key (a SHA-256 hash) that `fleche` uses to identify this specific call in the cache. This is derived from the function name, arguments, and other metadata." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2026-03-20T00:49:51.369235Z", "iopub.status.busy": "2026-03-20T00:49:51.369046Z", "iopub.status.idle": "2026-03-20T00:49:51.373190Z", "shell.execute_reply": "2026-03-20T00:49:51.372197Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cache Key: 44a75ca3f502c3f7d86c9cb057840f8e1d07494e69f16f3e396bb4ae2a9d9a3e\n" ] } ], "source": [ "key = slow_add.digest(10, b=20)\n", "print(f\"Cache Key: {key}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. `.contains(*args, **kwargs)`\n", "\n", "You can use `.contains` to check if a result for a specific set of arguments is already present in the cache, without triggering the function execution." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2026-03-20T00:49:51.375001Z", "iopub.status.busy": "2026-03-20T00:49:51.374787Z", "iopub.status.idle": "2026-03-20T00:49:52.379867Z", "shell.execute_reply": "2026-03-20T00:49:52.378894Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Is (10, 20) in cache? False\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Is (10, 20) in cache now? True\n" ] } ], "source": [ "print(f\"Is (10, 20) in cache? {slow_add.contains(10, b=20)}\")\n", "\n", "# Now we run it to populate the cache\n", "slow_add(10, b=20)\n", "\n", "print(f\"Is (10, 20) in cache now? {slow_add.contains(10, b=20)}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. `.load(*args, **kwargs)`\n", "\n", "The `.load` method allows you to explicitly retrieve a result from the cache. If the result is not in the cache, it will raise a `KeyError` instead of executing the function." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2026-03-20T00:49:52.381996Z", "iopub.status.busy": "2026-03-20T00:49:52.381698Z", "iopub.status.idle": "2026-03-20T00:49:52.386504Z", "shell.execute_reply": "2026-03-20T00:49:52.385479Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Loaded result: 30\n", "Result for (1, 2) not in cache.\n" ] } ], "source": [ "result = slow_add.load(10, b=20)\n", "print(f\"Loaded result: {result}\")\n", "\n", "try:\n", " slow_add.load(1, 2)\n", "except KeyError:\n", " print(\"Result for (1, 2) not in cache.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. `.rerun(*args, **kwargs)`\n", "\n", "The `.rerun` method allows you to force a re-execution of the function, even if the result is already in the cache. It will save the new result to the cache, and recursively force any nested `@fleche` calls to re-execute as well." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2026-03-20T00:35:38.187368Z", "iopub.status.busy": "2026-03-20T00:35:38.187006Z", "iopub.status.idle": "2026-03-20T00:35:39.196375Z", "shell.execute_reply": "2026-03-20T00:35:39.194733Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rerun Result: 30 (took 1.00 seconds forcing execution)\n", "Normal call Result: 30 (took 0.00 seconds)\n" ] } ], "source": [ "start = time.time()\n", "res = slow_add.rerun(10, b=20)\n", "end = time.time()\n", "print(f\"Rerun Result: {res} (took {end - start:.2f} seconds forcing execution)\")\n", "\n", "# subsequent calls will be fast again\n", "start = time.time()\n", "res2 = slow_add(10, b=20)\n", "end = time.time()\n", "print(f\"Normal call Result: {res2} (took {end - start:.2f} seconds)\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6. `.__wrapped__`\n", "\n", "Because `fleche` uses `functools.wraps`, the original undecorated function is always available via the `.__wrapped__` attribute. This is useful if you want to bypass the cache entirely. Unlike `.rerun`, calling the `.__wrapped__` function does *not* save the result to the cache, nor does it force nested cached functions to re-execute." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2026-03-20T00:35:39.200013Z", "iopub.status.busy": "2026-03-20T00:35:39.199628Z", "iopub.status.idle": "2026-03-20T00:35:40.206202Z", "shell.execute_reply": "2026-03-20T00:35:40.204641Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Result: 30 (took 1.00 seconds bypassing cache)\n" ] } ], "source": [ "start = time.time()\n", "res = slow_add.__wrapped__(10, 20)\n", "end = time.time()\n", "print(f\"Result: {res} (took {end - start:.2f} seconds bypassing cache)\")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.13" } }, "nbformat": 4, "nbformat_minor": 4 }