Summary
constants=None means "construct a fresh private Constants()" — a sentinel that means the opposite of what None conventionally means (the default here is the shared config), documented under a "Potential Gotcha" heading. 1.4 ships the explicit vocabulary and the deprecation warning; removal is #261 (2.0).
HumanName(name) # shared CONSTANTS (unchanged)
HumanName(name, constants=Constants()) # private, library defaults
HumanName(name, constants=CONSTANTS.copy()) # private, snapshot of current shared config
The trap the sentinel can't express
"Give me a private config" is ambiguous between fresh library defaults and a private snapshot of the current shared config. None silently picks the first: customize CONSTANTS.titles, later pass None for "my own config", and the customizations are gone with no error. An explicit Constants argument forces the caller to answer the question; the missing piece is a nice spelling for the snapshot answer — copy.deepcopy(CONSTANTS) works (reliably since the 1.3.0 pickle/deepcopy fixes, which is what makes this cheap now), but nobody discovers deepcopy for config.
Checklist
Summary
constants=Nonemeans "construct a fresh privateConstants()" — a sentinel that means the opposite of whatNoneconventionally means (the default here is the shared config), documented under a "Potential Gotcha" heading. 1.4 ships the explicit vocabulary and the deprecation warning; removal is #261 (2.0).The trap the sentinel can't express
"Give me a private config" is ambiguous between fresh library defaults and a private snapshot of the current shared config.
Nonesilently picks the first: customizeCONSTANTS.titles, later passNonefor "my own config", and the customizations are gone with no error. An explicitConstantsargument forces the caller to answer the question; the missing piece is a nice spelling for the snapshot answer —copy.deepcopy(CONSTANTS)works (reliably since the 1.3.0 pickle/deepcopy fixes, which is what makes this cheap now), but nobody discoversdeepcopyfor config.Checklist
Constants.copy()— deepcopy-based detached copy;_on_changerewiring is already handled by the deepcopy machinery landed in 1.3.0DeprecationWarningwhenconstants=Noneis passed explicitly, naming both replacements. Only explicitNonewarns — the signature default isCONSTANTS, so omitting the argument never hits the branchConstants | Nonestays for 1.4, docstring marksNonedeprecated)