"""Memoized namedtuple class factory.

collections.namedtuple builds a new class (compiling generated source) on
every call.  Callers that derive a namedtuple from runtime data -- column
names from a query, keys of an API response -- would otherwise rebuild the
same class on every request.  cached_namedtuple caches the class by name and
field tuple so it is built once per distinct schema.
"""
from collections import namedtuple
from functools import lru_cache


@lru_cache(maxsize=None)
def cached_namedtuple(name, fields):
    """Return a namedtuple class, memoized by (name, fields).

    ``fields`` must be a tuple of field names so the arguments are hashable.
    """
    return namedtuple(name, fields)
