A tool for light-duty persistent memoization of API calls

Overview

JSON Memoize

What is this?

json_memoize is a straightforward tool for light-duty persistent memoization, created with API calls in mind. It stores the arguments passed to a function and that function call's returned value in a dict, and writes that dict's contents to disk in a .json file.

Arguments at a glance

  • max_age - sets the maximum allowed age in seconds before a cached entry is considered invalid.
  • max_size - sets the maximum number of entries that can be stored in the cache.
  • force_update - overwrites cached values with fresh ones.
  • cache_folder_path - sets the location of the associated .json file.
  • app_name - if no cache_folder_path is provided, app_name is used to create a folder in the default user cache folder.
  • cache_file_name - manually sets the name of the cache file.

Basic Use

Import and add the decorator @memoize to memoize a function.

Warning: json_memoize stores arguments passed to memoized functions in a plain text format. Do not pass your API key, or any other sensitive information, to memoized functions.

Here's a slow api call:

def slow_api_call(arg_1:str, arg_2: str) -> str:
    response = requests.get(f"https://wowthistakesforever.slow/arg-1={arg_1}&arg-2={arg_2}")
    return response.text

Add the @memoize decorator to memoize it.

from json_memoize import memoize

@memoize
def slow_api_call(arg_1:str, arg_2: str) -> str:
    response = requests.get(f"https://wowthistakesforever.slow/arg-1={arg_1}&arg-2={arg_2}")
    return response.text

If the function is called again with the same arguments, the resulting value will be retrieved from the cache without executing the function.

max_age

If you don't want to keep data that's too old, you can set a max age.

@memoize(max_age=600)
def slow_api_call(arg_1:str, arg_2: str) -> str:
    ...

The age of an entry is determined from the time it was first added to the cache. If the difference between that time and the current time exceeds the max_age value, the cached value will be overwritten with a fresh one. Entries that have exceeded max_age will not be written to disk. If max_age is not set, cache entries will not expire. Note: max_age is in seconds. Consider creating variables for measures of time that are inconvenient or unclear when written in seconds, e.g.:

one_week = 604_800
@memoize(max_age=one_week)
    ...

max_size

If you don't want to cache too many entries, you can set a maximum number of entries to store.

@memoize(max_size=10)
def slow_api_call(arg_1:str, arg_2: str) -> str:
    ...

If max_size is set, json_memoize will delete cache entries from oldest to youngest until it meets the specified size limit before it saves the file to disk. As with max_age, the age of an entry is determined by the time at which it was first added to the cache, not when it was most recently used. Note: The size limit is only enforced when the cache file is being written. While the JsonCache object is live in memory, the limit can be exceeded.

force_update

If something in your ecosystem has changed and you want to force the cached values to be updated with fresh information, you can do that too.

@memoize(force_update=True)
def slow_api_call(arg_1:str, arg_2: str) -> str:
    ...

If force_update is True, all entries in the cache will be overwritten, even if they have not yet reached max_age.

Setting the Cache Folder

To reduce the likelihood of name collisions, json_memoize stores its cache files in named folders. There are multiple ways to specify where this folder is located.

Automatic folder creation using app_name

If a value is provided for app_name, json_memoize will use this value to name a new folder within the operating systems preferred user cache folder. e.g.:

@memoize(app_name='my_app') will create a folder structure like ".cache/my_app/"

Manual cache folder assignment

If a cache_folder argument is supplied to the decorator, it will store cache files in that folder. Note: if cache_folder is supplied, it will overrule app_name.

Default folder location

Warning: Not recommended!

If neither cache_folder nor app_name is provided, json_memoize will use its default folder name, yielding a folder structure like ".cache/json_memoize/"

This is not recommended, as intermingling cache files from multiple apps increases the risk of file name collisions, which could cause apps to behave unpredictably.

Naming Cache Files

By default, json_memoize will create each cache file using the name of the function being memoized, e.g.:

@memoize
def slow_api_call():
    ... 

This will create a file called "slow_api_call_cahce.json".

Setting a custom file name with cahce_file_name

If a value is provided for cache_file_name, json_memoize will instead use this value to name the cache file.

Storage and Performance Details

Storage

When a call is made to a memoized function, json_memoize will generate a string from the passed arguments, and use that string as the key in its internal cache dictionary. The value returned by the call is stored as the associated value. Writing this dict to disk is accomplished using json.dump(). Seperate cache files are made for each memoized function.

Warning: It is assumed here that @memoize will be invoked in situations where both the arguments and the returned value of a function have consistent, unambiguous string representations. Passing arguments with unreliable string representation will cause the cache to behave unpredictably. json_memoize will log a warning if it detects something that looks like a repr() output that points to a memory address in an incoming argument. Also, once again, do not pass security-relevant information to memoized functions.

Performance

json_memoize is intended to be performant relative to a slow API call, and has not been optimized further than that. If max_size is exceeded, the entries in the dict are sorted so the oldest ones can be dropped. Setting aside hard drive performance, this sorting operation is the most costly step of the process, and it occurs every time the cahce file is saved.

rTorrent Crash Prevention

rTorrent Disk Checker This program is capable of the following when: - a torrent is added by any program (autodl-irssi, RSS Downloader et

16 Dec 14, 2022
Rotazioni: a linear programming workout split optimizer

Rotazioni: a linear programming workout split optimizer Dependencies Dependencies for the frontend and backend are respectively listed in client/packa

Marco 3 Oct 13, 2022
Monitor the New World login queue and notify when it is about to finish

nwwatch - Monitor the New World queue and notify when it is about to finish Getting Started install python 3.7+ navigate to the directory where you un

14 Jan 10, 2022
Hacktoberfest 2021 contribution repository✨

🎃 HacktoberFest-2021 🎃 Repository for Hacktoberfest Note: Although, We are actively focusing on Machine Learning, Data Science and Tricky Python pro

Manjunatha Sai Uppu 42 Dec 11, 2022
GUI for the Gammu library.

Wammu GUI for the Gammu library. Homepage https://wammu.eu/ License GNU GPL version 3 or later. First start On first start you will be asked for set

Gammu 60 Dec 14, 2022
Fuzz introspector for python

Fuzz introspector High-level goals: Show fuzzing-relevant data about each function in a given project Show reachability of fuzzer(s) Integrate seamles

14 Mar 25, 2022
hey, this repo is the backend of the sociio project

sociio backend Hey, this repository is a part of sociio project , In this repo we are working to create an independent server for everything you can i

2 Jun 09, 2022
Very efficient backup system based on the git packfile format, providing fast incremental saves and global deduplication

Very efficient backup system based on the git packfile format, providing fast incremental saves and global deduplication (among and within files, including virtual machine images). Current release is

bup 6.9k Dec 27, 2022
A Company Management System For Python

campany-management Getting started To make it easy for you to get started with GitLab, here's a list of recommended next steps. Already a pro? Just ed

hatice akpınar 3 Aug 29, 2022
objectfactory is a python package to easily implement the factory design pattern for object creation, serialization, and polymorphism

py-object-factory objectfactory is a python package to easily implement the factory design pattern for object creation, serialization, and polymorphis

Devin A. Conley 6 Dec 14, 2022
GibMacOS - Py2/py3 script that can download macOS components direct from Apple

Py2/py3 script that can download macOS components direct from Apple Can also now build Internet Recovery USB installers from Windows using dd and 7zip

CorpNewt 4.8k Jan 02, 2023
PyPI package for scaffolding out code for decision tree models that can learn to find relationships between the attributes of an object.

Decision Tree Writer This package allows you to train a binary classification decision tree on a list of labeled dictionaries or class instances, and

2 Apr 23, 2022
Markov Chain Composer

Markov Chain Composer Using Markov Chain to represent relationships between words in song lyrics and then generating new lyrics.. ahem interpretive po

Kylie 85 Dec 09, 2022
🎉 🎉 PyComp - Java Code compiler written in python.

🎉 🎉 PyComp Java Code compiler written in python. This is yet another compiler meant for babcock students project which was created using pure python

Alumona Benaiah 5 Nov 30, 2022
This is the old code for bitcoin risk metric, the whole purpose form it is to help you DCA your investment according to bitcoin risk.

About The Project This is the old code for bitcoin risk metric, the whole purpose form it is to help you DCA your investment according to bitcoin risk

BitcoinRaven 2 Aug 03, 2022
Ahmed Hossam 12 Oct 17, 2022
propuestas electorales de los candidatos a constituyentes, Chile 2021

textos-constituyentes propuestas electorales de los candidatos a constituyentes, Chile 2021 Programas descargados desde https://elecciones2021.servel.

Sergio Lucero 6 Nov 19, 2021
Subcert is an subdomain enumeration tool, that finds all the subdomains from certificate transparency logs.

Subcert Subcert is a subdomain enumeration tool, that finds all the valid subdomains from certificate transparency logs. Table of contents Setup Demo

A3h1nt 59 Dec 16, 2022
dragmap-meth: Fast and accurate aligner for bisulfite sequencing reads using dragmap

dragmap_meth (dragmap_meth.py) Alignment of BS-Seq reads using dragmap. Intro This works for single-end reads and for paired-end reads from the direct

Shaojun Xie 3 Jul 14, 2022
Stop python warnings, no matter what!

SHUTUP - Stop python warnings, no matter what! Sometimes you just can't mute python warnings. Use this library to solve this. Installation pip install

80 Jan 04, 2023