GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-141510, PEP 814: Add built-in frozendict type by vstinner · Pull Request #144757 · python/cpython

Conversation

@vstinner

@vstinner vstinner commented Feb 12, 2026 •
edited by hugovk
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Add TYPE_FROZENDICT to the marshal module.

Add C API functions:

  • PyAnyDict_Check()
  • PyAnyDict_CheckExact()
  • PyFrozenDict_Check()
  • PyFrozenDict_CheckExact()
  • PyFrozenDict_New()

Add PyFrozenDict_Type C type.

  • Issue: PEP 814: Add built-in frozendict type #141510

📚 Documentation preview 📚: https://cpython-previews--144757.org.readthedocs.build/en/144757/c-api/dict.html#frozen-dictionary-objects

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

johnslavik, corona10, and sergey-miryanov reacted with rocket emoji
All reactions
  • 🚀 3 reactions
@vstinner
pythongh-141510, PEP 814: Add built-in frozendict type
bde4379
Add TYPE_FROZENDICT to the marshal module.

Add C API functions:

* PyAnyDict_Check()
* PyAnyDict_CheckExact()
* PyFrozenDict_Check()
* PyFrozenDict_CheckExact()
* PyFrozenDict_New()

Add PyFrozenDict_Type C type.
@bedevere-app bedevere-app Bot mentioned this pull request Feb 12, 2026
PEP 814: Add built-in frozendict type #141510
Closed
vstinner added 2 commits February 12, 2026 19:25
@vstinner
Document PyFrozenDict_Type in the C API doc
1fb7c5a
@vstinner
Fix test_inspect and test_doctest
fca2e5b
@vstinner
vstinner marked this pull request as ready for review February 13, 2026 07:30
@vstinner
vstinner requested review from AA-Turner, ZeroIntensity, ericsnowcurrently, markshannon, methane and rhettinger as code owners February 13, 2026 07:30
@bedevere-app bedevere-app Bot added the awaiting core review label Feb 13, 2026
@vstinner
Complete the documentation
99b291c
@vstinner

vstinner commented Feb 13, 2026

Copy link
Copy Markdown
Member Author

cc @corona10

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner vstinner mentioned this pull request Feb 13, 2026
[WIP] gh-141510: PEP 814: Add built-in frozendict type #141508
Closed
@vstinner
Fix doc warnings
5e4a284
Fix also indentation.
@corona10
corona10 self-requested a review February 13, 2026 10:07
hugovk
hugovk reviewed Feb 13, 2026
View reviewed changes
Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/whatsnew/3.15.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/mapping_tests.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/mapping_tests.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@vstinner @hugovk
Apply suggestions from code review
5c0c6f1
Co-authored-by: Hugo van Kemenade <[email protected]>
kumaraditya303
kumaraditya303 reviewed Feb 13, 2026
View reviewed changes
Comment thread Objects/dictobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

corona10
corona10 reviewed Feb 13, 2026
View reviewed changes
Comment thread Objects/dictobject.c
}

if (PyDict_CheckExact(d)) {
if (PyAnyDict_CheckExact(d)) {

@corona10 corona10 Feb 13, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Maybe same opinion with @kumaraditya303 we can avoid a lot of critical section if dict is frozen dict.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Feb 13, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I agree, but I would prefer to make such "optimization" change in a separated PR.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
corona10
corona10 reviewed Feb 13, 2026
View reviewed changes
Comment thread Objects/dictobject.c
dict_length(PyObject *self)
{
return FT_ATOMIC_LOAD_SSIZE_RELAXED(((PyDictObject *)self)->ma_used);
return GET_USED(_PyAnyDict_CAST(self));

@corona10 corona10 Feb 13, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Do we have to use atomic operation for frozendict?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Feb 13, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

No, we can skip the atomic operation for frozendict.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@kumaraditya303 kumaraditya303 Feb 13, 2026

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

It uses relaxed atomic so it compiles to simple loads so avoiding it has no real benefit.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Feb 17, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

len(frozendict) has been optimized by #144913.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
corona10
corona10 reviewed Feb 13, 2026
View reviewed changes
Comment thread Objects/dictobject.c
};

static PyMappingMethods frozendict_as_mapping = {
.mp_length = dict_length,

@corona10 corona10 Feb 13, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I think that we can make frozendict_lenth

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Feb 13, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I propose to make such optimization in a separated PR.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
corona10
corona10 reviewed Feb 13, 2026
View reviewed changes
Comment thread Objects/dictobject.c

static PyMappingMethods frozendict_as_mapping = {
.mp_length = dict_length,
.mp_subscript = dict_subscript,

@corona10 corona10 Feb 13, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Still perfer to make frozendict_subscript, but let's do it at the separate PR.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

vstinner reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
corona10
corona10 reviewed Feb 13, 2026
View reviewed changes

@corona10 corona10 left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

We should notice that frozendict is not subclass of dict to follow SC feedback

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
vstinner and others added 3 commits February 13, 2026 15:46
@vstinner @hugovk
Apply suggestion from @hugovk
8d4ed14
Co-authored-by: Hugo van Kemenade <[email protected]>
@vstinner
Move the What's New entry
c770613
Document frozendict after lazy import.
@vstinner
Revert _PyDict_LoadBuiltinsFromGlobals() change
6dfec48
vstinner
vstinner commented Feb 13, 2026
View reviewed changes
Comment thread Objects/dictobject.c
mp->ma_values == NULL &&
(mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3))
(mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3) &&
!frozendict)

@vstinner vstinner Feb 13, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

We might take this fast-path for frozendict as well. It's just a missed optimization opportunity.

@corona10: Add it to the optimization TODO list :-)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

corona10 reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@corona10 corona10 Feb 13, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Yeah I will take a look at it

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Objects/dictobject.c
if (items == NULL) {
return -1;
}
PyObject *frozenset = PyFrozenSet_New(items);

@vstinner vstinner Feb 13, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

The current implementation creates an actual frozenset object which emits surprising error messages:

>>> hash(frozendict(x=[]))
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    hash(frozendict(x=[]))
    ~~~~^^^^^^^^^^^^^^^^^^
TypeError: cannot use 'tuple' as a set element (unhashable type: 'list')

We may change the implementation later to not create an actual frozenset, but reuse frozenset hash code instead, to avoid the surprising errors.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Feb 17, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I changed the implementation in #144919.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@vstinner
Document that frozendict is not a dict subclass
9101b1a
@vstinner

vstinner commented Feb 13, 2026

Copy link
Copy Markdown
Member Author

We should notice that frozendict is not subclass of dict to follow SC feedback

Ah right, done.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@corona10 corona10 added the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label Feb 14, 2026
@bedevere-bot

bedevere-bot commented Feb 14, 2026

Copy link
Copy Markdown

🤖 New build scheduled with the buildbot fleet by @corona10 for commit 9101b1a 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F144757%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-refleak-buildbots label again.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-bot bedevere-bot removed the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label Feb 14, 2026
@corona10

corona10 commented Feb 14, 2026

Copy link
Copy Markdown
Member

Let's wait build bot to pass the refleak test :)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

benediktjohannes
benediktjohannes reviewed Feb 14, 2026
View reviewed changes

@benediktjohannes benediktjohannes left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Nitpick: I know this does not primarily belong to the PR, but it's such a small change that a new PR wouldn't make sense for these small "typos".

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

adamchainz
adamchainz reviewed Feb 15, 2026
View reviewed changes
Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

@vstinner @adamchainz
Update Doc/library/stdtypes.rst
e845b2b
Co-authored-by: Adam Johnson <[email protected]>
@vstinner

vstinner commented Feb 16, 2026

Copy link
Copy Markdown
Member Author

Let's wait build bot to pass the refleak test :)

Tests passed successfully on Refleaks buildbots:

buildbot/AMD64 CentOS9 NoGIL Refleaks PR — Build done.
buildbot/AMD64 Fedora Stable Refleaks PR — Build done.
buildbot/AMD64 FreeBSD Refleaks PR — Build done.
buildbot/AMD64 RHEL8 Refleaks PR — Build done.
buildbot/AMD64 Windows11 Refleaks PR — Build done.
buildbot/ARM64 MacOS M1 Refleaks NoGIL PR — Build done.
buildbot/PPC64LE Fedora Stable Refleaks PR — Build done.
buildbot/PPC64LE RHEL8 Refleaks PR — Build done.
buildbot/s390x Fedora Stable Refleaks PR — Build done.
buildbot/s390x RHEL8 Refleaks PR — Build done.
buildbot/s390x RHEL9 Refleaks PR — Build done.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

hugovk
hugovk reviewed Feb 16, 2026
View reviewed changes
Comment thread Doc/c-api/dict.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/c-api/dict.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/c-api/dict.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/c-api/dict.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/c-api/dict.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/c-api/dict.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/c-api/dict.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

vstinner and others added 2 commits February 16, 2026 13:01
@vstinner @hugovk
Apply suggestions from code review
3d08f46
Co-authored-by: Hugo van Kemenade <[email protected]>
@vstinner
doc: use sentence case for headers
258b3df
Add also a title in Doc/library/stdtypes.rst.
@vstinner

vstinner commented Feb 16, 2026

Copy link
Copy Markdown
Member Author

@hugovk: I modified a few more titles in the C API doc and the Python doc to use sentence case for headers.

hugovk reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

corona10
corona10 approved these changes Feb 16, 2026
View reviewed changes

@corona10 corona10 left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

lgtm with current implementations , I will soon create PRs for removing unneeded overhead from my side.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting core review labels Feb 16, 2026
sergey-miryanov
sergey-miryanov reviewed Feb 16, 2026
View reviewed changes

@sergey-miryanov sergey-miryanov left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Couple of nitpicks.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Objects/dictobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/dictobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/dictobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/dictobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/dictobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

hugovk
hugovk reviewed Feb 16, 2026
View reviewed changes
Comment thread Doc/whatsnew/3.15.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/whatsnew/3.15.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

vstinner and others added 2 commits February 16, 2026 21:33
@vstinner
Add tests on repr(frozendict)
09abcf5
@vstinner @hugovk
Apply suggestions from code review
3653eeb
Co-authored-by: Hugo van Kemenade <[email protected]>
benediktjohannes
benediktjohannes reviewed Feb 16, 2026
View reviewed changes
Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/stdtypes.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

benediktjohannes
benediktjohannes reviewed Feb 16, 2026
View reviewed changes
Comment thread Lib/test/mapping_tests.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/mapping_tests.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@vstinner @benediktjohannes
Apply suggestions from code review
5bc207a
Co-authored-by: Benedikt Johannes <[email protected]>
@vstinner
vstinner merged commit 696cdfc into python:main Feb 17, 2026
47 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@vstinner
vstinner deleted the frozendict_base branch February 17, 2026 09:54
@bedevere-app bedevere-app Bot removed the awaiting merge label Feb 17, 2026
@vstinner

vstinner commented Feb 17, 2026

Copy link
Copy Markdown
Member Author

I merged my PR. Thank you very much for all your reviews!

sergey-miryanov and hugovk reacted with rocket emoji
All reactions
  • 🚀 2 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@savannahostrowski savannahostrowski mentioned this pull request Feb 18, 2026
dict_traverse crash during PGO training on Windows with JIT enabled #144970
Closed
brijkapadia pushed a commit to brijkapadia/cpython that referenced this pull request Feb 28, 2026
@vstinner @hugovk
@adamchainz @benediktjohannes @brijkapadia
pythongh-141510, PEP 814: Add built-in frozendict type (python#144757)
1044beb
Add TYPE_FROZENDICT to the marshal module.

Add C API functions:

* PyAnyDict_Check()
* PyAnyDict_CheckExact()
* PyFrozenDict_Check()
* PyFrozenDict_CheckExact()
* PyFrozenDict_New()

Add PyFrozenDict_Type C type.

Co-authored-by: Hugo van Kemenade <[email protected]>
Co-authored-by: Adam Johnson <[email protected]>
Co-authored-by: Benedikt Johannes <[email protected]>
ljfp pushed a commit to ljfp/cpython that referenced this pull request Apr 25, 2026
@vstinner @hugovk
@adamchainz @benediktjohannes @ljfp
pythongh-141510, PEP 814: Add built-in frozendict type (python#144757)
fa77761
Add TYPE_FROZENDICT to the marshal module.

Add C API functions:

* PyAnyDict_Check()
* PyAnyDict_CheckExact()
* PyFrozenDict_Check()
* PyFrozenDict_CheckExact()
* PyFrozenDict_New()

Add PyFrozenDict_Type C type.

Co-authored-by: Hugo van Kemenade <[email protected]>
Co-authored-by: Adam Johnson <[email protected]>
Co-authored-by: Benedikt Johannes <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@sergey-miryanov sergey-miryanov sergey-miryanov left review comments
@hugovk hugovk hugovk left review comments
@kumaraditya303 kumaraditya303 kumaraditya303 left review comments
@corona10 corona10 corona10 approved these changes
@rhettinger rhettinger Awaiting requested review from rhettinger rhettinger is a code owner
@ericsnowcurrently ericsnowcurrently Awaiting requested review from ericsnowcurrently ericsnowcurrently is a code owner
@ZeroIntensity ZeroIntensity Awaiting requested review from ZeroIntensity ZeroIntensity is a code owner
@methane methane Awaiting requested review from methane methane is a code owner
@markshannon markshannon Awaiting requested review from markshannon markshannon is a code owner
@AA-Turner AA-Turner Awaiting requested review from AA-Turner AA-Turner is a code owner
+2 more reviewers
@adamchainz adamchainz adamchainz left review comments
@benediktjohannes benediktjohannes benediktjohannes left review comments
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

8 participants

@vstinner @bedevere-bot @corona10 @sergey-miryanov @adamchainz @hugovk @kumaraditya303 @benediktjohannes
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.