Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/release_log.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Release Log
===========
* 1.3.0 - Unreleased

**Upgrade note — pickle migration**: ``Constants`` pickles written before
1.2.1 cannot be loaded under 1.3.0+. If you have persisted blobs, upgrade
to 1.2.1 first (which includes a one-version compatibility shim), load and
re-pickle under 1.2.1, then upgrade to 1.3.0.

- Add ``suffix_delimiter`` to ``Constants`` and ``HumanName`` for parsing suffixes separated by arbitrary delimiters, e.g. ``"RN - CRNA"`` (#156)
- Add ``initials_separator`` to ``Constants`` and ``HumanName`` to control spacing between consecutive initials within a name group (#171)
- Fix ``Constants`` customizations, singleton identity, and ``TupleManager`` subclass being lost across ``pickle``/``deepcopy`` round-trips (#167, #168, #169)
Expand Down
10 changes: 0 additions & 10 deletions nameparser/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,16 +383,6 @@ def __setstate__(self, state: Mapping[str, Any]) -> None:
# unpickling.
self._pst = None
for name, value in state.items():
# Migration shim: pickles written before this fix used a dir() sweep
# for __getstate__, so their state carries the read-only
# ``suffixes_prefixes_titles`` property. Skip any such computed
# property rather than raising AttributeError on its missing setter;
# the real config is restored from the other keys. We don't promise
# to read pre-fix blobs forever — this only smooths migration for
# anyone persisting them, and can be dropped a release or two after
# 1.2.1 once they've re-pickled.
if isinstance(getattr(type(self), name, None), property):
continue
setattr(self, name, value)
# Verify each descriptor-backed attr was restored. Without this, a missing
# key surfaces later as AttributeError: 'Constants' object has no attribute
Expand Down
25 changes: 0 additions & 25 deletions tests/test_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,31 +208,6 @@ def test_tuplemanager_ignores_dunder_lookups(self) -> None:
# A normal (non-dunder) unknown key still returns the None default.
self.assertEqual(tm.unknown_key, None)

def test_unpickle_legacy_state_with_property_key(self) -> None:
"""Pickles written by older versions must still load.

The previous __getstate__ built its state from a dir() sweep, which
always included the computed `suffixes_prefixes_titles` property (no
customization required). That property has no setter, so __setstate__
must skip such keys instead of raising AttributeError.

Covers the temporary migration shim in __setstate__; remove this test
when that shim is dropped (a release or two after 1.2.1).
"""
c = Constants()
c.titles.add('legacytitle')
# Reproduce the legacy dir()-sweep state dict, which carries the
# read-only `suffixes_prefixes_titles` property alongside the real config.
legacy_state = {
name: getattr(c, name) for name in dir(c) if not name.startswith('_')
}
self.assertIn('suffixes_prefixes_titles', legacy_state)

restored = Constants.__new__(Constants)
restored.__setstate__(legacy_state)

# The real customization is recovered and the property key is ignored.
self.assertIn('legacytitle', restored.titles)

def test_suffixes_prefixes_titles_reflects_add_title(self) -> None:
"""suffixes_prefixes_titles must include titles added after construction."""
Expand Down