### Install perscache Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Installation command for the package. ```bash pip install perscache ``` -------------------------------- ### Changing Default Serialization and Storage Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Illustrates how to configure a `Cache` instance with custom `serializer` and `storage` backends. This example sets up `JSONSerializer` and `GoogleCloudStorage` as defaults. ```python # set up serialization format and storage backend cache = Cache( serializer=JSONSerializer(), storage=GoogleCloudStorage("/bucket/folder") ) ... # change the default serialization format @cache(serialization=PickleSerializer()) def get_data(key): ... ``` -------------------------------- ### Initialize Cache with Google Cloud Storage Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md Demonstrates how to initialize the Cache class with GoogleCloudStorage. Ensure 'gcsfs' is installed. The storage_options parameter is used to pass configuration to the underlying GCSFilesystem. ```python from perscache import Cache from perscache.storage import GoogleCloudStorage cache = Cache( storage=GoogleCloudStorage( location="my-bucket/cache", storage_options={"token": "my-token.json"} ) ) @cache def get_data(): ... ``` -------------------------------- ### Creating a Custom Serializer Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Provides an example of creating a custom serializer by inheriting from `perscache.serializers.Serializer`. This allows for custom data serialization and deserialization, with a specified file extension. ```python from perscache.serializers import Serializer class MySerializer(Serializer): extension = "data" def dumps(self, data: Any) -> bytes: ... def loads(self, data: bytes) -> Any: ... cache = Cache(serializer=MySerializer()) ``` -------------------------------- ### Custom In-Memory Storage Backend Source: https://context7.com/leshchenko1979/perscache/llms.txt Implement a custom storage backend by extending the `Storage` base class. This example provides a simple in-memory storage for testing purposes, with `read` and `write` methods. ```python import datetime as dt from pathlib import Path from typing import Union from perscache import Cache from perscache.storage import Storage, CacheExpired class InMemoryStorage(Storage): """Simple in-memory storage for testing.""" def __init__(self): self._store = {} self._timestamps = {} def read(self, path: Union[str, Path], deadline: dt.datetime) -> bytes: key = str(path) if key not in self._store: raise FileNotFoundError(f"No cache entry for {key}") if deadline and self._timestamps[key] < deadline: raise CacheExpired() return self._store[key] def write(self, path: Union[str, Path], data: bytes) -> None: key = str(path) self._store[key] = data self._timestamps[key] = dt.datetime.now(dt.timezone.utc) cache = Cache(storage=InMemoryStorage()) @cache def compute(x: int) -> int: return x * 2 result = compute(5) # Cached in memory ``` -------------------------------- ### Enable Debug Logging for Perscache Source: https://context7.com/leshchenko1979/perscache/llms.txt Configure logging to view cache hits, misses, and hash generation details. This setup helps in debugging cache behavior. ```python import logging from perscache import Cache logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger("perscache") logger.addHandler(logging.StreamHandler()) logger.setLevel(logging.DEBUG) cache = Cache() @cache def cached_function(x: int) -> int: return x * 2 result = cached_function(5) # Logs show: hash generation, cache miss/hit, file operations ``` -------------------------------- ### Create Custom XML Serializer Source: https://context7.com/leshchenko1979/perscache/llms.txt Use `make_serializer` to quickly define a custom serializer for XML data. This example shows how to specify dump and load functions for a simple XML format. ```python XMLSerializer = make_serializer( class_name="XMLSerializer", ext="xml", dumps_fn=lambda data: f"{data}".encode("utf-8"), loads_fn=lambda data: data.decode("utf-8").replace("", "").replace("", "") ) cache = Cache(serializer=XMLSerializer()) @cache def get_message(key: str) -> str: return f"Hello, {key}!" result = get_message("world") # File: .cache/get_message-.xml # Contents: Hello, world! ``` -------------------------------- ### Create Custom Compressed JSON Serializer Source: https://context7.com/leshchenko1979/perscache/llms.txt Extend the `Serializer` base class to create a custom serializer for compressed JSON data. This example implements `dumps` and `loads` methods using `gzip` and `json` modules. ```python from perscache import Cache from perscache.serializers import Serializer from typing import Any class CompressedJSONSerializer(Serializer): extension = "json.gz" def dumps(self, data: Any) -> bytes: import gzip import json json_bytes = json.dumps(data).encode("utf-8") return gzip.compress(json_bytes) def loads(self, data: bytes) -> Any: import gzip import json json_bytes = gzip.decompress(data) return json.loads(json_bytes.decode("utf-8")) cache = Cache(serializer=CompressedJSONSerializer()) @cache def get_large_data(key: str) -> dict: return {"key": key, "payload": "x" * 10000} result = get_large_data("test") # File: .cache/get_large_data-.json.gz (compressed) ``` -------------------------------- ### GoogleCloudStorage Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md Stores cache entries in separate files within a Google Cloud Storage Bucket. Requires the `gcsfs` module to be installed. ```APIDOC ## GoogleCloudStorage ### Description Keeps cache entries in separate files in a Google Cloud Storage Bucket. Relies on the [`gcsfs`](https://pypi.org/project/gcsfs/) module, which is not a part of the project dependencies and needs to to be installed by the user if he is to use this class. ### Parameters #### Path Parameters - **location** (str) - Required - A directory to store the cache files. Defaults to `".cache"`. - **max_size** (int) - Optional - The maximum size for the cache. If set, then, before a new cache entry is written, the future size of the directory is calculated and the least recently used cache entries are removed. If `None`, the cache size grows indefinitely. Defaults to `None`. - **storage_options** (dict) - Optional - A dictionary of parameters to pass to the constructor of the `GSCFilesystem` class of the [`gcsfs`](https://pypi.org/project/gcsfs/) module (see the module documentation for more information). Defaults to `None`. ### Request Example ```python # supposing gcsfs is installed from perscache import Cache from perscache.storage import GoogleCloudStorage cache = Cache( storage=GoogleCloudStorage( location="my-bucket/cache", storage_options={"token": "my-token.json"} ) ) @cache def get_data(): ... ``` ``` -------------------------------- ### Override Cache Serialization with Parquet Source: https://context7.com/leshchenko1979/perscache/llms.txt Use the ParquetSerializer to cache DataFrame results. Ensure pandas is installed. ```python from perscache import cache from perscache.serializers import ParquetSerializer @cache(serializer=ParquetSerializer()) def load_dataframe(source: str): import pandas as pd return pd.DataFrame({"col1": [1, 2, 3]}) ``` -------------------------------- ### Use basic caching Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Demonstrates function result persistence across calls. ```python from perscache import Cache cache = Cache() counter = 0 @cache def get_data(): print("Fetching data...") global counter counter += 1 return "abc" print(get_data()) # the function is called # Fetching data... # abc print(get_data()) # the cache is used # abc print(counter) # the function was called only once # 1 ``` -------------------------------- ### Configure Instance Method Caching Source: https://context7.com/leshchenko1979/perscache/llms.txt Demonstrates per-instance versus shared caching for class methods using the per_instance parameter. ```python from perscache import Cache cache = Cache() class DataProcessor: def __init__(self, name: str): self.name = name self.call_count = 0 @cache # Default: per_instance=True - each instance has separate cache def process(self, value: int) -> int: self.call_count += 1 print(f"{self.name} processing {value}...") return value * 2 @cache(per_instance=False) # Shared cache across all instances def compute_shared(self, value: int) -> int: self.call_count += 1 print(f"{self.name} computing shared {value}...") return value ** 2 # Per-instance caching (default) proc1 = DataProcessor("Processor1") proc2 = DataProcessor("Processor2") result1 = proc1.process(10) # Output: Processor1 processing 10... result2 = proc1.process(10) # No output - cache hit for proc1 result3 = proc2.process(10) # Output: Processor2 processing 10... (separate cache) # Shared caching result4 = proc1.compute_shared(5) # Output: Processor1 computing shared 5... result5 = proc2.compute_shared(5) # No output - shared cache hit ``` -------------------------------- ### Create Custom Serializer Source: https://context7.com/leshchenko1979/perscache/llms.txt Initializes a custom serializer using the make_serializer factory function. ```python from perscache import Cache from perscache.serializers import make_serializer ``` -------------------------------- ### Implement a custom storage back-end Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Define a custom storage class by implementing the read and write methods required by the Storage interface. ```python class MyStorage(Storage): def read(self, path, deadline: datetime.datetime) -> bytes: """Read the file at the given path and return its contents as bytes. If the file does not exist, raise FileNotFoundError. If the file is older than the given deadline, raise CacheExpired. """ ... def write(self, path, data: bytes) -> None: """Write the file at the given path.""" ... cache = Cache(storage=MyStorage()) ``` -------------------------------- ### Implement Basic Persistent Caching Source: https://context7.com/leshchenko1979/perscache/llms.txt Use the Cache decorator to persist function results to the local filesystem using pickle serialization. ```python from perscache import Cache cache = Cache() # Basic usage - cache results to local .cache directory using pickle serialization @cache def fetch_expensive_data(user_id: int) -> dict: print(f"Fetching data for user {user_id}...") # Simulate expensive operation return {"user_id": user_id, "name": "John Doe", "balance": 1000} # First call - function executes result1 = fetch_expensive_data(42) # Output: Fetching data for user 42... # Second call - returns cached result without executing function result2 = fetch_expensive_data(42) # No output - cache hit # Different arguments trigger new execution result3 = fetch_expensive_data(99) # Output: Fetching data for user 99... ``` -------------------------------- ### Use YAML Serializer Source: https://context7.com/leshchenko1979/perscache/llms.txt Configures the cache to use YAML serialization, which requires the yaml package. ```python from perscache import Cache from perscache.serializers import YAMLSerializer cache = Cache(serializer=YAMLSerializer()) @cache def get_schema(table_name: str) -> dict: return { "table": table_name, "columns": ["id", "name", "created_at"], "primary_key": "id" } # Result cached as .yaml file schema = get_schema("users") # File: .cache/get_schema-.yaml ``` -------------------------------- ### Conditional Caching Based on Environment Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Shows how to dynamically configure caching based on environment variables. In debug mode, `NoCache` is used to disable caching; otherwise, it defaults to `GoogleCloudStorage` or `LocalFileStorage`. ```python import os from perscache import Cache, NoCache from perscache.storage import LocalFileStorage if os.environ.get["DEBUG"]: cache = NoCache() # turn off caching in debug mode else: cache = ( GoogleCloudStorage("/bucket/folder") if os.environ.get["GOOGLE_PROJECT_NAME"] # if running in the cloud else LocalFileStorage() ) @cache def function(): ... ``` -------------------------------- ### Async Function Caching Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Demonstrates caching for asynchronous functions. The first call to `fetch_data` will execute the function body, while subsequent calls with the same arguments will retrieve the result from the cache. ```python @cache async def fetch_data(url: str): print("Fetching data...") response = await some_async_request(url) return response # First call fetches data1 = await fetch_data("example.com") # Second call uses cache data2 = await fetch_data("example.com") ``` -------------------------------- ### Mixed Serializer and Storage Configuration Source: https://context7.com/leshchenko1979/perscache/llms.txt Configure default serializer and storage at the cache level, and override them on a per-function basis. This allows for flexible caching strategies. ```python from perscache import Cache from perscache.serializers import JSONSerializer, CloudPickleSerializer, ParquetSerializer from perscache.storage import LocalFileStorage # Default: CloudPickle serializer with local storage cache = Cache( serializer=CloudPickleSerializer(), storage=LocalFileStorage(location=".cache", max_size=50 * 1024 * 1024) ) # Use default settings @cache def complex_computation(data: list) -> object: return {"result": sum(data), "type": "complex"} # Override with JSON for human-readable output @cache(serializer=JSONSerializer()) def get_config(name: str) -> dict: return {"name": name, "enabled": True} ``` -------------------------------- ### Local File Storage with Max Size Source: https://context7.com/leshchenko1979/perscache/llms.txt Configure `LocalFileStorage` to save cache files to a specified directory with a maximum size limit. This enables automatic cleanup of least recently used entries when the cache exceeds the limit. ```python from perscache import Cache from perscache.storage import LocalFileStorage # Cache with 100MB limit and automatic cleanup storage = LocalFileStorage( location=".my_cache", # Custom cache directory max_size=100 * 1024 * 1024 # 100 MB limit ) cache = Cache(storage=storage) @cache def download_file(url: str) -> bytes: print(f"Downloading {url}...") # Simulate download return b"file contents" * 1000 # Files cached in .my_cache directory # LRU cleanup happens automatically when cache exceeds 100MB data = download_file("https://example.com/file.bin") ``` -------------------------------- ### Create a custom serializer with make_serializer Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Use the factory function to define custom serialization and deserialization logic for specific data types. ```python import pyrogram from perscache.serializers import make_serializer PyrogramSerializer = make_serializer( "PyrogramSerializer", "pyro", dumps_fn = lambda data: str(data).encode("utf-8"), loads_fn = lambda data: eval(data.decode("utf-8")), ) cache = Cache(serializer=PyrogramSerializer()) @cache async def some_pyrogram_func() -> pyrogram.Message: ... ``` -------------------------------- ### Setting Cache Expiry Time Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Configures a cache with a time-to-live (TTL) of one day using `datetime.timedelta`. The cached data will be considered stale and recomputed after this period. ```python import datetime as dt @cache(ttl=dt.timedelta(days=1)) def get_data(): """This function will be cached for 1 day and called again after this period expires.""" ... ``` -------------------------------- ### Use JSON Serializer Source: https://context7.com/leshchenko1979/perscache/llms.txt Configures the cache to use JSON serialization for human-readable cache files. ```python from perscache import Cache from perscache.serializers import JSONSerializer cache = Cache(serializer=JSONSerializer()) @cache def get_config(app_name: str) -> dict: return { "app_name": app_name, "version": "1.0.0", "settings": {"debug": False, "log_level": "INFO"} } # Result cached as .json file in .cache directory config = get_config("myapp") # File: .cache/get_config-.json # Contents: {"app_name": "myapp", "version": "1.0.0", ...} ``` -------------------------------- ### Create Custom Serializer Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md Use `make_serializer` to create a custom serializer class. Provide a class name, file extension, and functions for dumping and loading data. This allows integration with custom serialization logic. ```python from perscache.serializers import make_serializer from perscache import Cache PyrogramSerializer = make_serializer( class_name = 'PyrogramSerializer', ext = 'pyrogram', dumps_fn = lambda x: str(x).encode('utf-8'), loads_fn = lambda x: eval(x.decode('utf-8')), ) cache = Cache() @cache(serializer=PyrogramSerializer()) def get_data(): ... ``` -------------------------------- ### Use Parquet and CSV Serializers for DataFrames Source: https://context7.com/leshchenko1979/perscache/llms.txt Demonstrates caching pandas DataFrames using Parquet for performance or CSV for readability. ```python import pandas as pd from perscache import Cache from perscache.serializers import ParquetSerializer, CSVSerializer # Parquet serializer with compression (requires pyarrow) cache_parquet = Cache(serializer=ParquetSerializer(compression="brotli")) @cache_parquet def load_large_dataset(source: str) -> pd.DataFrame: print(f"Loading data from {source}...") return pd.DataFrame({ "id": range(1000), "value": [i * 2 for i in range(1000)] }) # CSV serializer for human-readable cache (requires pandas) cache_csv = Cache(serializer=CSVSerializer()) @cache_csv def get_summary_stats(dataset_name: str) -> pd.DataFrame: return pd.DataFrame({ "metric": ["mean", "median", "std"], "value": [100.5, 98.0, 15.2] }) df = load_large_dataset("database") # Cached as .parquet stats = get_summary_stats("sales") # Cached as .csv ``` -------------------------------- ### Cache with Shared Instance Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md Configure the Cache decorator with `per_instance=False` to share a cache across all instances of a class. This is useful for instance methods where you want a single cache for all objects. ```python from perscache import Cache class DataFetcher: def __init__(self): self.compute_count = 0 @cache(per_instance=False) # Share cache between instances def fetch_data(self, key: str) -> str: self.compute_count += 1 return f"Fetched data for key: {key}" fetcher1 = DataFetcher() fetcher2 = DataFetcher() # First instance computes and caches result1 = fetcher1.fetch_data("test_key") # compute_count = 1 # Second instance uses the same cache result2 = fetcher2.fetch_data("test_key") # compute_count still 1 ``` -------------------------------- ### Override Cache Storage with LocalFileStorage Source: https://context7.com/leshchenko1979/perscache/llms.txt Specify a custom storage location using LocalFileStorage for the cache. ```python from perscache import cache from perscache.storage import LocalFileStorage @cache(storage=LocalFileStorage(location=".api_cache")) def call_api(endpoint: str) -> dict: return {"endpoint": endpoint, "data": "response"} ``` -------------------------------- ### Google Cloud Storage Backend Source: https://context7.com/leshchenko1979/perscache/llms.txt Use `GoogleCloudStorage` to store cache files in a GCS bucket. This requires the `gcsfs` package and proper authentication. ```python from perscache import Cache from perscache.storage import GoogleCloudStorage # GCS storage with authentication storage = GoogleCloudStorage( location="my-bucket/cache", max_size=1024 * 1024 * 1024, # 1 GB limit storage_options={"token": "path/to/credentials.json"} ) cache = Cache(storage=storage) @cache def process_cloud_data(dataset_id: str) -> dict: print(f"Processing dataset {dataset_id}...") return {"id": dataset_id, "status": "processed"} # Results cached to gs://my-bucket/cache/ result = process_cloud_data("dataset_001") ``` -------------------------------- ### Cache instance methods Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Configures caching behavior for class methods with instance-specific or shared storage. ```python class Calculator: def __init__(self): self.compute_count = 0 @cache # Default per_instance=True def add(self, a: int, b: int) -> int: self.compute_count += 1 return a + b @cache(per_instance=False) # Share cache between instances def multiply(self, a: int, b: int) -> int: self.compute_count += 1 return a * b calc1 = Calculator() calc2 = Calculator() # First call computes the result result1 = calc1.add(5, 3) # compute_count = 1 # Second call uses cache result2 = calc1.add(5, 3) # compute_count still 1 # Different instance gets its own cache result3 = calc2.add(5, 3) # calc2.compute_count = 1 # Shared cache between instances result4 = calc1.multiply(4, 2) # compute_count = 2 # Second instance uses the same cache result5 = calc2.multiply(4, 2) # compute_count still 2 ``` -------------------------------- ### Disable Caching with NoCache Source: https://context7.com/leshchenko1979/perscache/llms.txt Uses NoCache as a drop-in replacement to disable caching based on environment variables. ```python import os from perscache import Cache, NoCache # Toggle caching based on environment if os.environ.get("DEBUG"): cache = NoCache() # Disable caching in debug mode else: cache = Cache() @cache def expensive_calculation(x: int) -> int: print(f"Computing {x}...") return x ** 2 # With NoCache: function always executes # With Cache: function result is cached after first call result = expensive_calculation(5) ``` -------------------------------- ### perscache.serializers.make_serializer Function Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md Creates a custom serializer class derived from perscache.serializers.Serializer. ```APIDOC ### function `perscache.serializers.make_serializer()` #### Description This function is used to create a serializer class. #### Arguments - **class_name** (str) - The name of the serializer class. - **ext** (str) - The extension of the serialized file. - **dumps_fn** (Callable) - The function used to serialize an object into bytes. Accepts a single argument, the object to serialize, and returns a bytes object. - **loads_fn** (Callable) - The function used to deserialize bytes into an object. Accepts a single argument, the bytes to deserialize, and returns an object. #### Returns A serializer class derived from `perscache.serializers.Serializer` that can be used with `perscache.Cache`. #### Example ```python from perscache.serializers import make_serializer from perscache import Cache PyrogramSerializer = make_serializer( class_name = 'PyrogramSerializer', ext = 'pyrogram', dumps_fn = lambda x: str(x).encode('utf-8'), loads_fn = lambda x: eval(x.decode('utf-8')), ) cache = Cache() @cache(serializer=PyrogramSerializer()) def get_data(): ... ``` ``` -------------------------------- ### Ignoring Function Arguments for Cache Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Demonstrates how to ignore specific arguments when caching. The cache will not be invalidated even if the value of the `ignore_this` argument changes. ```python @cache(ignore="ignore_this") def get_data(key, ignore_this): print("The function has been called...") return key print(get_data("abc", "ignore_1")) # the function has been called # The function has been called... # abc # using the cache although the the second argument is different print(get_data("abc", "ignore_2")) # abc ``` -------------------------------- ### LocalFileStorage Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md Stores cache entries in separate files within a specified file system directory. This is the default storage class for Cache. ```APIDOC ## LocalFileStorage ### Description Keeps cache entries in separate files in a file system directory. This is the default storage class used by `Cache`. ### Parameters #### Path Parameters - **location** (str) - Required - A directory to store the cache files. Defaults to `".cache"`. - **max_size** (int) - Optional - The maximum size for the cache. If set, then, before a new cache entry is written, the future size of the directory is calculated and the least recently used cache entries are removed. If `None`, the cache grows indefinitely. Defaults to `None`. ``` -------------------------------- ### Serializer Classes Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md Available serializer classes for perscache. ```APIDOC ## Serializers Serializers are imported from the `perscache.serializers` module. ### class `perscache.serializers.Serializer` #### Description The abstract base serializer class. See also [how to make your own serializer](/README.md#make-your-own-serialization-and-storage-backends). ### class `perscache.serializers.CloudPickleSerializer` #### Description Uses the `cloudpickle` module. It's the most capable serializer of all, able to process most of the data types. It's the default serializer for the `Cache` class. ### class `perscache.serializers.JSONSerializer` #### Description Uses the `json` module. ### class `perscache.serializers.YAMLSerializer` #### Description Uses the `yaml` module. ### class `perscache.serializers.PickleSerializer` #### Description Uses the `pickle` module. ``` -------------------------------- ### Configure Cache TTL Source: https://context7.com/leshchenko1979/perscache/llms.txt Set an expiration time for cached results using the ttl parameter with a timedelta object. ```python import datetime as dt from perscache import Cache cache = Cache() @cache(ttl=dt.timedelta(hours=1)) def get_exchange_rate(currency: str) -> float: """Fetch exchange rate - cached for 1 hour.""" print(f"Fetching live rate for {currency}...") # Simulate API call return 1.12 if currency == "EUR" else 0.85 # First call fetches fresh data rate = get_exchange_rate("EUR") # Output: Fetching live rate for EUR... # Within 1 hour - uses cached value rate = get_exchange_rate("EUR") # No output - cache hit # After TTL expires, function executes again automatically ``` -------------------------------- ### Basic Cache Usage Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md Use the Cache decorator to cache function results. The cache is invalidated if the function code, arguments, or serializer change. ```python from perscache import Cache cache = Cache() @cache def get_data(): ... ``` -------------------------------- ### Logging Cache Operations Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md Add a StreamHandler to the 'perscache' logger to view log messages related to cache operations. ```python import logging logging.getLogger('perscache').addHandler(logging.StreamHandler()) ``` -------------------------------- ### Exclude Arguments from Cache Key Source: https://context7.com/leshchenko1979/perscache/llms.txt Use the ignore parameter to prevent specific arguments from affecting the cache key, useful for session-specific or non-functional data. ```python from perscache import Cache cache = Cache() @cache(ignore=["request_id", "timestamp"]) def fetch_user_profile(user_id: int, request_id: str, timestamp: float) -> dict: print(f"Fetching profile for user {user_id}...") return {"user_id": user_id, "name": "Alice", "email": "alice@example.com"} # First call - executes function profile1 = fetch_user_profile(1, "req-abc", 1699900000.0) # Output: Fetching profile for user 1... # Different request_id and timestamp - still uses cache because they're ignored profile2 = fetch_user_profile(1, "req-xyz", 1699900999.0) # No output - cache hit (request_id and timestamp are ignored) # Different user_id - cache miss profile3 = fetch_user_profile(2, "req-abc", 1699900000.0) # Output: Fetching profile for user 2... ``` -------------------------------- ### Cache Invalidation by Function Changes Source: https://github.com/leshchenko1979/perscache/blob/master/README.md Shows how changing the code of a decorated function invalidates the cache. The cache is recomputed when the function's implementation is modified. ```python @cache def get_data(key): print("The function has been called...") return key print(get_data("abc")) # the function has been called # The function has been called... # abc print(get_data("fgh")) # the function has been called again # The function has been called... # fgh print(get_data("abc")) # using the cache # abc @cache def get_data(key): print("This function has been changed...") return key print(get_data("abc")) # the function has been called again # This function has been changed... # abc ``` -------------------------------- ### perscache.NoCache Class Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md A class that disables caching. Useful for alternating cache behavior based on environment. ```APIDOC ## class `perscache.NoCache()` ### Description This class has no parameters. It is useful to [alternate cache behaviour depending on the environment](../README.md#alternating-cache-settings-depending-on-the-environment). ### decorator `perscache.NoCache().__call__()` #### Description The underlying function will be called every time the decorated function has been called and no caching will take place. This decorator will ignore any parameters it has been given. ``` -------------------------------- ### NoCache Decorator Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md Use the `NoCache` decorator to ensure a function is always called without any caching. This decorator ignores any parameters passed to it. ```python from perscache import NoCache @NoCache() def always_compute_data(): ... ``` -------------------------------- ### Cache Asynchronous Functions Source: https://context7.com/leshchenko1979/perscache/llms.txt Apply the cache decorator to async functions to maintain persistent caching for coroutines. ```python import asyncio from perscache import Cache cache = Cache() @cache async def fetch_data_async(endpoint: str) -> dict: print(f"Fetching from {endpoint}...") await asyncio.sleep(0.1) # Simulate network delay return {"endpoint": endpoint, "data": "response"} async def main(): # First call - executes async function result1 = await fetch_data_async("/api/users") # Output: Fetching from /api/users... # Second call - returns cached result result2 = await fetch_data_async("/api/users") # No output - cache hit asyncio.run(main()) ``` -------------------------------- ### perscache.Cache Class Source: https://github.com/leshchenko1979/perscache/blob/master/docs/api_reference.md The main Cache class for managing cached data. It can be used as a decorator to cache function results. ```APIDOC ## class `perscache.Cache()` ### Description Initializes a Cache object with optional serializer and storage back-ends. ### Parameters - **serializer** (perscache.serializers.Serializer) - Optional - A serializer class to use for converting stored data. Defaults to `perscache.serlializers.PickleSerializer`. - **storage** (perscache.storage.Storage) - Optional - A storage back-end used to save and load data. Defaults to `perscache.storage.LocalFileStorage`. ### decorator `perscache.Cache().__call__()` #### Description Tries to find a cached result of the decorated function in persistent storage. Returns the saved result if it was found, or calls the decorated function and caches its result. #### Arguments - **ignore** (str | Iterable[str]) - Optional - Arguments of the decorated function that will not be used in making the cache key. Defaults to `None`. - **serializer** (perscache.serializers.Serializer) - Optional - Overrides the default `Cache()` serializer. Defaults to `None`. - **storage** (perscache.storage.Storage) - Optional - Overrides the default `Cache()` storage. Defaults to `None`. - **ttl** (datetime.timedelta) - Optional - The time-to-live of the cache for the decorated function. If `None`, the cache never expires. Defaults to `None`. - **per_instance** (bool) - Optional - Whether to create a separate cache for each instance of a class. Defaults to `True`. #### Usage Example ```python from perscache import Cache cache = Cache() @cache def get_data(): ... ``` #### Example with shared cache ```python class DataFetcher: def __init__(self): self.compute_count = 0 @cache(per_instance=False) # Share cache between instances def fetch_data(self, key: str) -> str: self.compute_count += 1 return f"Fetched data for key: {key}" fetcher1 = DataFetcher() fetcher2 = DataFetcher() # First instance computes and caches result1 = fetcher1.fetch_data("test_key") # compute_count = 1 # Second instance uses the same cache result2 = fetcher2.fetch_data("test_key") # compute_count still 1 ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.