Skip to content

gh-141510, PEP 814: Add frozendict support to pickle#144967

Open
vstinner wants to merge 8 commits intopython:mainfrom
vstinner:frozendict_pickle2
Open

gh-141510, PEP 814: Add frozendict support to pickle#144967
vstinner wants to merge 8 commits intopython:mainfrom
vstinner:frozendict_pickle2

Conversation

@vstinner
Copy link
Member

@vstinner vstinner commented Feb 18, 2026

Add frozendict.__getnewargs__() method.

Add frozendict.__getnewargs__() method.
# make sure that floats are formatted locale independent with proto 0
self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')

def test_frozendict(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would not be better to add this test in test_frozendict.py? Together with tests for copy() and deepcopy()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I moved this test to test_pickle.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Together with tests for copy() and deepcopy()?

Commit dd64e42, which adds frozendict support to the copy module, added frozendict tests to test_copy.

@vstinner
Copy link
Member Author

@serhiy-storchaka: I addressed your review. Please review the updated PR.

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about frozendict views and iterators? Are they copyable/pickleable?

Are there tests for deepcopying?

I am surprised that there is no separate test_frozendict.py.

@serhiy-storchaka
Copy link
Member

Oh, I don't think deepcopy of frozendict is correct. It does not work for recursive frozendict.

@vstinner
Copy link
Member Author

I will try to update my PR later to address other comments.

What about frozendict views and iterators? Are they copyable/pickleable?

keys, values and items views cannot be copied nor serialized by pickle.

Ah, it seems like it's possible to serialize a frozendict iterator.

Are there tests for deepcopying?

test_copy.test_deepcopy_frozendict() tests frozendict deepcopy.

I am surprised that there is no separate test_frozendict.py.

Ah. It was simple to add frozendict tests to existing test_dict. Maybe we can create test_frozendict later once we will add more tests.

@vstinner
Copy link
Member Author

Oh, I don't think deepcopy of frozendict is correct. It does not work for recursive frozendict.

You're right, the current copy.deepcopy() implementation doesn't work for recursive frozendict.

@vstinner
Copy link
Member Author

I completed the PR to add requested tests.

@vstinner
Copy link
Member Author

You're right, the current copy.deepcopy() implementation doesn't work for recursive frozendict.

I created #145027 to fix copy.deepcopy() for recursive frozendict.

pickle.dumps(fd, proto)

def test_pickle_iter(self):
it = iter(frozendict(x=1, y=2))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about value iterator and item iterator?

Consume one item from the iterator, to ensure that it correctly restores its state. See pickling tests in test_ordered_dict for example.

If things are pickleable, they should also be deepcopyable. It is worth to have explicit deepcopy tests, because they can preserve additional invariants. For example, it should be possible to deepcopy a frozendict containing lambdas or modules.


def _test_recursive_collection_in_key(self, factory, minprotocol=0):
protocols = range(minprotocol, pickle.HIGHEST_PROTOCOL + 1)
key = DictKey()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use Object(), isn't?

Comment on lines +2950 to +2954
def test_recursive_dict_in_value(self):
self._test_recursive_collection_in_value(dict)

def test_recursive_dict_subclass_in_value(self):
self._test_recursive_collection_in_value(MyDict)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not add anything in comparison with test_recursive_dict and test_recursive_dict_subclass. The new tests are only needed for immutable frozendict (like there are special tests for tuple and frozenset).

Comment on lines +2927 to +2931
def test_recursive_dict_in_key(self):
self._test_recursive_collection_in_key(dict)

def test_recursive_dict_subclass_in_key(self):
self._test_recursive_collection_in_key(MyDict)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not add anything in comparison with more strong test_recursive_dict_key and test_recursive_dict_subclass_key.

Redundant tests make it harder to figure out what particular paths were tested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments