Skip to content

Commit 9abb861

Browse files
derek73claude
andcommitted
fix: re-wire pickle __getstate__ for descriptor-backed attrs
_CachedUnionMember stores prefixes/titles/etc. under a leading-underscore private name (_prefixes, _titles, …). The previous __getstate__ filtered out everything starting with '_', so those four attrs were silently dropped from every pickle. __setstate__ then had nothing to restore and accessed the class-level descriptor object rather than a SetManager. Fix: map '_xxx' back to 'xxx' when the attr is a _CachedUnionMember, so __setstate__ receives the public name and can restore through the descriptor, re-wiring _on_change callbacks in the process. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c7018c8 commit 9abb861

1 file changed

Lines changed: 17 additions & 8 deletions

File tree

‎nameparser/config/__init__.py‎

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -357,14 +357,23 @@ def __setstate__(self, state: Mapping[str, Any]) -> None:
357357
setattr(self, name, value)
358358

359359
def __getstate__(self) -> Mapping[str, Any]:
360-
# Pickle only the instance's own configuration: the collections built in
361-
# __init__ plus any instance-level scalar overrides. Class-level scalar
362-
# defaults are restored by the class itself, and underscore-prefixed
363-
# names such as the ``_pst`` cache are private and rebuilt on demand.
364-
# Filtering on ``self.__dict__`` also excludes the computed
365-
# ``suffixes_prefixes_titles`` property automatically, since properties
366-
# live on the class and never appear in an instance's ``__dict__``.
367-
return {k: v for k, v in self.__dict__.items() if not k.startswith('_')}
360+
# Pickle the instance's own configuration: the collections built in
361+
# __init__ plus any instance-level scalar overrides.
362+
# _CachedUnionMember descriptors store their values with a leading
363+
# underscore (e.g. `_prefixes` for `prefixes`) so that the descriptor's
364+
# __set__ owns assignment. We map those back to the public names so
365+
# __setstate__ can restore them through the descriptor, re-wiring the
366+
# invalidation callbacks. All other underscore-prefixed names (_pst, etc.)
367+
# are private/cache and are intentionally excluded.
368+
state: dict[str, Any] = {}
369+
for name, val in self.__dict__.items():
370+
if name.startswith('_'):
371+
public = name[1:]
372+
if isinstance(getattr(type(self), public, None), _CachedUnionMember):
373+
state[public] = val
374+
else:
375+
state[name] = val
376+
return state
368377

369378

370379
#: A module-level instance of the :py:class:`Constants()` class.

0 commit comments

Comments
 (0)