CARVIEW |
Select Language
HTTP/2 200
date: Mon, 13 Oct 2025 13:26:03 GMT
server: Fly/5d9a8537e (2025-10-13)
content-type: text/html; charset=utf-8
content-encoding: gzip
via: 2 fly.io, 2 fly.io
fly-request-id: 01K7EVZR3TVB2BNSBC1G2HDPMM-bom
Decorators with optional arguments | Simon Willison’s TILs
Decorators with optional arguments
sqlite-utils provides a decorator for registering custom Python functions that looks like this:
from sqlite_utils import Database
db = Database(memory=True)
@db.register_function
def reverse_string(s):
return "".join(reversed(list(s)))
I wanted to add an optional deterministic=True parameter to the decorator.
Problem: the decorator currently does not take any arguments. But I wanted this to work as well:
@db.register_function(deterministic=True)
def reverse_string(s):
return "".join(reversed(list(s)))
I don't want to break backwards compatibility with existing code.
First lesson: any time you are designing a decorator that might accept arguments in the future, design it to work like this!
@db.register_function()
def reverse_string(s):
return "".join(reversed(list(s)))
Since I hadn't done that, I needed an alternative pattern that could differentiate between the two ways in which the decorator might be called. I ended up going with this:
def register_function(self, fn=None, deterministic=None):
def register(fn):
name = fn.__name__
arity = len(inspect.signature(fn).parameters)
kwargs = {}
if deterministic and sys.version_info >= (3, 8):
kwargs["deterministic"] = True
self.conn.create_function(name, arity, fn, **kwargs)
return fn
if fn is None:
return register
else:
register(fn)
Related
- spatialite Creating a minimal SpatiaLite database with Python - 2021-12-17
- python Introspecting Python function parameters - 2020-05-27
- sphinx Adding Sphinx autodoc to a project, and configuring Read The Docs to build it - 2021-08-10
- sqlite Saving an in-memory SQLite database to a file in Python - 2023-04-08
- sqlite Loading SQLite extensions in Python on macOS - 2023-01-07
- sqlite Using LD_PRELOAD to run any version of SQLite with Python - 2020-06-17
- pytest Registering temporary pluggy plugins inside tests - 2020-07-21
- python Protocols in Python - 2023-07-26
- python Defining setup.py dependencies using a URL - 2022-08-13
- django Adding a Datasette ASGI app to Django - 2022-10-20
Created 2020-10-28T14:54:48-07:00, updated 2020-12-29T13:55:23-08:00 · History · Edit