Skip to content

Add Constants.copy(); deprecate constants=None #260

Description

@derek73

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

  • Add Constants.copy() — deepcopy-based detached copy; _on_change rewiring is already handled by the deepcopy machinery landed in 1.3.0
  • DeprecationWarning when constants=None is passed explicitly, naming both replacements. Only explicit None warns — the signature default is CONSTANTS, so omitting the argument never hits the branch
  • Update the signature annotation in the same PR (Constants | None stays for 1.4, docstring marks None deprecated)
  • Docs in the same PR: the three-spelling vocabulary in customize.rst and a sentence on the defaults-vs-snapshot distinction

Metadata

Metadata

Assignees

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions