Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 52
Description
Description of the bug
When displaying (with some options detailed later) a module attribute initialized with dictionary comprehension, the documentation shows incorrect Python code and random characters.
For example,
TEST_0_INDEX_BY_KEY={obj.key: objforobjin []}Is displayed in the documentation generated by mkdocs as:
TEST_0_INDEX_BY_KEY={(key): _Hlforobjin []}The options I used to trigger this behaviour were separate_signature: true and signature_crossrefs: true.
To Reproduce
I reproduced using 3 files:
test_dict.py
TEST_0_INDEX_BY_KEY={obj.key: objforobjin []} """Showing `(key): <random characters>` instead of `obj.key: obj`."""TEST_1_ACCESS_MEMBER={obj: obj.memberforobjin []} """Showing `obj: (member)` instead of `obj: obj.member`."""TEST_2_LONG_NAME={some_object_with_a_long_name: some_object_with_a_long_nameforsome_object_with_a_long_namein [] } """Showing `some_object_with_a_long_name: <more random characters>` instead of `some_object_with_a_long_name: some_object_with_a_long_name`."""mkdocs.yml
site_name: Test Python dict comprehensionplugins: - mkdocstrings: handlers: python: options: separate_signature: truesignature_crossrefs: truedocs/index.md
::: test_dictThe 3 files can be created with this command (which uses a base64-encoded tar.gz archive):
echo H4sIAAAAAAACA+3WUWvbMBAAYD/7Vxx5ah/myYljg+kGbWfG2JKNJQ8rYyiurcReI8tICl0Y++87OzFLN3Cg0IzCfS+OrYvucO5QrDCW52VmvXrrPBGGwjBor+jvK4uiyPHHLPKDMAiZ7zB/6I98B5hzAhtjUw3gaKVsX9yx9WdqnszmnPF30zfJF351w98nN/AKfqrb796d2MaAH2CpdHstK/j67Zc7GAxmhbovqxUszjDoPIYLnVa5kpAVqU4zK7R5vcBwY0Wag1rC4nC/hYc7uG6b2eeX19fJbMYnyeQq+bxP3YZ5Ushbofuyt6Fnu7jzfxIe7nKYc8g/fJy+5dPLSdLkcwEZJQXHcJFZfl/agqd8raoVr1Ip4t7V9utNjX1Bu+Ldh9X357yQSgs49l4fX/fujTjyLleZ8bZy/XQ9dmz+Ryzo5n8cDUc4//44YjT/p2BKK/bdMsejAD5tbaEqaE4EyJSstShEZUpVuW693qyw92Ls+Bew6xursZPbJ40Cm3WNPdrdA9Ttbn/uAVRtcTNz+AinT9TY31iIKVdVajcaq7F6Ix4GdWs808oYLZZmH+WQR2t+xZdllYsfnsz/0/wzP+zmfzgehe35H4xp/k8hjnGIuv+ANEmEEEIIIYQQQgghhBBCCCGEEPJs/QaXqtegACgAAA== | base64 -d | tar -xz Then, install mkdocs and mkdocstrings-python and launch the server:
pip install mkdocs mkdocstrings-python mkdocs servehttp://127.0.0.1:8000/ shows:

The 3 Python snippets are:
TEST_0_INDEX_BY_KEY={(key): _Z5forobjin []} TEST_1_ACCESS_MEMBER={obj: (member)forobjin []} TEST_2_LONG_NAME={some_object_with_a_long_name: _6Jpv7OmLiQU4bm2xsgNeOyqDsdmforsome_object_with_a_long_namein []}It is also possible to run mkdocs build and read site/index.html:
Extract of site/index.html
<h2id="test_dict.TEST_0_INDEX_BY_KEY" class="doc doc-heading"><spanclass="doc doc-object-name doc-attribute-name">TEST_0_INDEX_BY_KEY</span><spanclass="doc doc-labels"><smallclass="doc doc-label doc-label-module-attribute"><code>module-attribute</code></small></span></h2><preclass="highlight"><codeclass="language-python doc-signature">TEST_0_INDEX_BY_KEY ={(<spantitle="obj.key">key</span>): _xEfor <spantitle="obj">obj</span> in []}</code></pre><divclass="doc doc-contents "><p>Showing <code>(key): <random characters></code> instead of <code>obj.key: obj</code>.</p></div></div><divclass="doc doc-object doc-attribute"><h2id="test_dict.TEST_1_ACCESS_MEMBER" class="doc doc-heading"><spanclass="doc doc-object-name doc-attribute-name">TEST_1_ACCESS_MEMBER</span><spanclass="doc doc-labels"><smallclass="doc doc-label doc-label-module-attribute"><code>module-attribute</code></small></span></h2><preclass="highlight"><codeclass="language-python doc-signature">TEST_1_ACCESS_MEMBER ={<spantitle="obj">obj</span>: (<spantitle="obj.member">member</span>)for <spantitle="obj">obj</span> in []}</code></pre><divclass="doc doc-contents "><p>Showing <code>obj: (member)</code> instead of <code>obj: obj.member</code>.</p></div></div><divclass="doc doc-object doc-attribute"><h2id="test_dict.TEST_2_LONG_NAME" class="doc doc-heading"><spanclass="doc doc-object-name doc-attribute-name">TEST_2_LONG_NAME</span><spanclass="doc doc-labels"><smallclass="doc doc-label doc-label-module-attribute"><code>module-attribute</code></small></span></h2><preclass="highlight"><codeclass="language-python doc-signature">TEST_2_LONG_NAME ={<spantitle="some_object_with_a_long_name">some_object_with_a_long_name</span>: _7kTCpbiedqLcznZoOnrjKhe3D9Gfor <spantitle="some_object_with_a_long_name">some_object_with_a_long_name</span> in []}</code></pre><divclass="doc doc-contents "><p>Showing <code>some_object_with_a_long_name: <more random characters></code> instead of <code>some_object_with_a_long_name: some_object_with_a_long_name</code>.</p></div></div>TEST_0_INDEX_BY_KEY={(obj.key): objforobjin []} TEST_1_ACCESS_MEMBER={obj: (obj.member)forobjin []} TEST_2_LONG_NAME={some_object_with_a_long_name: some_object_with_a_long_nameforsome_object_with_a_long_namein []}With separate_signature: true and without signature_crossrefs: true, obj. disappears from the first two reproducers:
TEST_0_INDEX_BY_KEY={(key): objforobjin []} TEST_1_ACCESS_MEMBER={obj: (member)forobjin []} TEST_2_LONG_NAME={some_object_with_a_long_name: some_object_with_a_long_nameforsome_object_with_a_long_namein []}Expected behavior
I expect the Python code displayed by mkdocs to be consistent.
Environment information
I tested in a Python 3.13 container with the current git main version:
podman run --rm --net=host -it docker.io/library/python:3.13 bash pip install 'git+https://github.com/mkdocs/mkdocs' pip install 'git+https://github.com/mkdocstrings/python'This installed:
$ pip freezeclick==8.3.0colorama==0.4.6ghp-import==2.1.0griffe==1.14.0Jinja2==3.1.6Markdown==3.9MarkupSafe==3.0.3mergedeep==1.3.4mkdocs @ git+https://github.com/mkdocs/mkdocs@f68e5fc18d3cd3811dbddfdeda1a57721f9e2e4emkdocs-autorefs==1.4.3mkdocs-get-deps==0.2.0mkdocstrings==0.30.1mkdocstrings-python @ git+https://github.com/mkdocstrings/python@f25b2ecf73f30ac0ea836bec1aa60e87a360e23apackaging==25.0pathspec==0.12.1platformdirs==4.4.0pymdown-extensions==10.16.1python-dateutil==2.9.0.post0PyYAML==6.0.3pyyaml_env_tag==1.1six==1.17.0watchdog==6.0.0python -m mkdocstrings_handlers.python._internal.debug # | xclip -selection clipboard- System: Linux-6.8.0-85-generic-x86_64-with-glibc2.39
- Python: cpython 3.13.0 (/usr/local/bin/python)
- Environment variables:
- Installed packages:
mkdocstrings-pythonv1.18.3.dev1+gf25b2ec
I also tested with uv and several Python versions:
uv run --python python3.13 --with mkdocs --with mkdocstrings-python mkdocs serve uv run --python python3.14 --with mkdocs --with mkdocstrings-python mkdocs serveAdditional context
I encountered this issue in a project where several classes are defined (ClsA, ClsB, ClsC), a global variable listes the classes (ALL_CLASSES = (ClsA, ClsB, ClsC)) and another global variable enables getting a class through their name:
CLASS_BY_NAME={cls.name: clsforclsinALL_CLASSES}The documentation generated by mkdocs was buggy and this is what led to the first minimal reproducer I shared (TEST_0_INDEX_BY_KEY ={obj.key: obj for obj in []}).