Skip to main content

Ensure a function runs only once, regardless of how many times it's called

Project description

philiprehberger-once

Tests PyPI version Last updated

Ensure a function runs only once, regardless of how many times it's called.

Installation

pip install philiprehberger-once

Usage

from philiprehberger_once import once

@once
def load_config():
    print("Loading...")
    return {"debug": True}

load_config()  # prints "Loading...", returns {"debug": True}
load_config()  # returns {"debug": True} without printing

Async support

import asyncio
from philiprehberger_once import once

@once
async def fetch_token():
    print("Fetching...")
    return "abc-123"

asyncio.run(fetch_token())  # prints "Fetching...", returns "abc-123"
asyncio.run(fetch_token())  # returns "abc-123" without fetching

Once per key

from philiprehberger_once import once_per_key

@once_per_key
def connect(host, port=5432):
    print(f"Connecting to {host}...")
    return f"conn:{host}"

connect("db-1")  # prints "Connecting to db-1...", returns "conn:db-1"
connect("db-1")  # returns cached "conn:db-1"
connect("db-2")  # prints "Connecting to db-2...", returns "conn:db-2"

Once per key (async)

import asyncio
from philiprehberger_once import once_per_key_async

@once_per_key_async
async def fetch_user(user_id: str):
    print(f"Fetching {user_id}...")
    return {"id": user_id}

async def main():
    # Concurrent awaiters of the same key share one in-flight execution.
    a, b, c = await asyncio.gather(
        fetch_user("u1"),
        fetch_user("u1"),
        fetch_user("u2"),
    )
    # Only two prints: one for "u1" and one for "u2".

asyncio.run(main())

# Derive the cache key from a callable instead of the first arg:
@once_per_key_async(key=lambda req, **kw: kw["uid"])
async def load(req, *, uid: str):
    return uid

Reset and inspect

from philiprehberger_once import once

@once
def init():
    return 42

init()
init.called   # True
init.reset()
init.called   # False
init()        # runs again

API

Function / Property Description
once(fn) Decorator. Runs fn once, caches and returns the result on subsequent calls. Thread-safe. Supports async.
once_per_key(fn) Decorator. Runs fn once per unique first argument. Thread-safe.
once_per_key_async(fn=None, *, key=None) Decorator for async functions. Runs the coroutine once per unique key (first positional arg, or derived via key=...). Concurrent awaiters of the same key share one in-flight execution.
.called bool for once, dict[key, bool] for once_per_key and once_per_key_async. Whether the function has been called.
.reset() Clear cached result so the function can run again. once_per_key and once_per_key_async accept an optional key argument.

Development

pip install -e .
python -m pytest tests/ -v

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

philiprehberger_once-0.2.0.tar.gz (7.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

philiprehberger_once-0.2.0-py3-none-any.whl (5.6 kB view details)

Uploaded Python 3

File details

Details for the file philiprehberger_once-0.2.0.tar.gz.

File metadata

  • Download URL: philiprehberger_once-0.2.0.tar.gz
  • Upload date:
  • Size: 7.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for philiprehberger_once-0.2.0.tar.gz
Algorithm Hash digest
SHA256 bdafa3997854963f68bc79e9a91c0aced8012d4952a4aa04fee5944dad15e4cd
MD5 44fabe604435f9017c417b9d88726ca1
BLAKE2b-256 d1af935e7b5e23ad52c1457ac6daf21858a95f4f5fc5b2e1940b49b5b633a2a7

See more details on using hashes here.

File details

Details for the file philiprehberger_once-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for philiprehberger_once-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6d5086d45f841dd228cab2099fc49dceebfc77fd14a92e3f1eb5640ce7bb27e6
MD5 d435e7d168f4223cd8ed2df5270da40c
BLAKE2b-256 d75def4352a73c99b4a7b5ab2e5e6d2f15d5f1942ce9e92bdf6b4e062609af2a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page