Skip to content

Missing keys in repro of tomlkit.container.OutOfOrderTableProxy #439

Closed

Description

@ewjoachim

Hello,
Here's a strange one.

From this toml:

a.b.c = "d"
a.b.e = "f"

When we access value["a"], it behaves correctly but the repr is missing the "c" key.

import tomlkit

print(tomlkit.__version__)
# 0.13.3

a = tomlkit.parse("""
a.b.c = "d"
a.b.e = "f"
""")
assert a == {"a": {"b": {"c": "d", "e": "f"}}}  # ok
value = a["a"]
expected = {"b": {"c": "d", "e": "f"}}
assert value == expected  # ok

print(value)
# {'b': {'e': 'f'}}
print(expected)
# {'b': {'c': 'd', 'e': 'f'}}

assert repr(value) == repr(expected)
# Traceback (most recent call last):
#   File "/Users/joachim/code/raincoat2/oops.py", line 19, in <module>
#     assert repr(value) == repr(expected)
#            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# AssertionError

As far as I can tell, this doesn't happen on a, only on a["a"].
I've tried to simplify the issue as much as possible.

Activity

  1. ewjoachim commented on Aug 1, 2025

    @ewjoachim
    Author

    If it helps to understand the issue: it also occurs in conjunction with pydantic:

    from __future__ import annotations
    
    import pydantic
    import tomlkit
    
    print(tomlkit.__version__)
    
    a = tomlkit.parse("""
    a.b.c = "d"
    a.b.e = "f"
    """)
    value = a["a"]
    
    
    class B(pydantic.BaseModel):
        c: str
        e: str
    
    
    class A(pydantic.BaseModel):
        b: B
    
    
    expected = {"b": {"c": "d", "e": "f"}}
    A.model_validate(expected)
    assert value == expected
    A.model_validate(value)
    # pydantic_core._pydantic_core.ValidationError: 1 validation error for A
    # b.c
    #   Field required [type=missing, input_value={'e': 'f'}, input_type=Table]
    #     For further information visit https://errors.pydantic.dev/2.11/v/missing

    But in that case, it makes sense to use unwrap, and the problem disappears.

  2. ewjoachim commented on Aug 1, 2025

    @ewjoachim
    Author

    I thought it was a perfect opportunity to do a bit of git bisect, but it came back with this commit of -1700+1700 lines, so not very helpful, I guess... Well, I tried :)

  3. ewjoachim commented on Aug 1, 2025

    @ewjoachim
    Author

    Ok, it was a nice rabbit hole, but (and I say it with immense respect for maintainers) every ten minutes I spend trying to understand the hierarchy of object inheriting dict which behaves both like an object and like a native dict, I have to roll for sanity, and I'm running low. I'll leave it to the pros :) Good luck !

  4. thatch commented on May 6, 2026

    @thatch

    Can you test this again on 0.14.0 -- seems to be fixed as part of change to fix #431

  5. ewjoachim commented on May 8, 2026

    @ewjoachim
    Author
    uv run -s - <<EOF
    # /// script
    # dependencies = [
    #   "tomlkit>=0.14.0",
    # ]
    # ///
    import tomlkit
    
    print(tomlkit.__version__)
    # 0.13.3
    
    a = tomlkit.parse("""
    a.b.c = "d"
    a.b.e = "f"
    """)
    assert a == {"a": {"b": {"c": "d", "e": "f"}}}  # ok
    value = a["a"]
    expected = {"b": {"c": "d", "e": "f"}}
    assert value == expected  # ok
    
    print(value)
    # {'b': {'e': 'f'}}
    print(expected)
    # {'b': {'c': 'd', 'e': 'f'}}
    
    assert repr(value) == repr(expected)
    EOF
    Installed 1 package in 4ms
    0.14.0
    {'b': {'e': 'f'}}
    {'b': {'c': 'd', 'e': 'f'}}
    Traceback (most recent call last):
      File "<string>", line 25, in <module>
        assert repr(value) == repr(expected)
               ^^^^
    

    Not fixed.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions