@@ -44,6 +44,7 @@ def body(self) -> list[tuple[Key | None, Item]]:
44
44
return self ._body
45
45
46
46
def unwrap (self ) -> dict [str , Any ]:
47
+ """Returns as pure python object (ppo)"""
47
48
unwrapped = {}
48
49
for k , v in self .items ():
49
50
if k is None :
@@ -64,6 +65,7 @@ def unwrap(self) -> dict[str, Any]:
64
65
65
66
@property
66
67
def value (self ) -> dict [str , Any ]:
68
+ """The wrapped dict value"""
67
69
d = {}
68
70
for k , v in self ._body :
69
71
if k is None :
@@ -145,7 +147,19 @@ def _get_last_index_before_table(self) -> int:
145
147
last_index = i
146
148
return last_index + 1
147
149
148
- def append (self , key : Key | str | None , item : Item ) -> Container :
150
+ def _validate_out_of_order_table (self , key : SingleKey | None = None ) -> None :
151
+ if key is None :
152
+ for k in self ._map :
153
+ assert k is not None
154
+ self ._validate_out_of_order_table (k )
155
+ return
156
+ if key not in self ._map or not isinstance (self ._map [key ], tuple ):
157
+ return
158
+ OutOfOrderTableProxy (self , self ._map [key ])
159
+
160
+ def append (
161
+ self , key : Key | str | None , item : Item , validate : bool = True
162
+ ) -> Container :
149
163
"""Similar to :meth:`add` but both key and value must be given."""
150
164
if not isinstance (key , Key ) and key is not None :
151
165
key = SingleKey (key )
@@ -227,8 +241,8 @@ def append(self, key: Key | str | None, item: Item) -> Container:
227
241
else :
228
242
self ._raw_append (key , item )
229
243
230
- # Building a temporary proxy to check for errors
231
- OutOfOrderTableProxy ( self , self ._map [ key ] )
244
+ if validate :
245
+ self ._validate_out_of_order_table ( key )
232
246
233
247
return self
234
248
@@ -286,7 +300,7 @@ def append(self, key: Key | str | None, item: Item) -> Container:
286
300
self ._raw_append (key , item )
287
301
return self
288
302
289
- def _raw_append (self , key : Key , item : Item ) -> None :
303
+ def _raw_append (self , key : Key | None , item : Item ) -> None :
290
304
if key in self ._map :
291
305
current_idx = self ._map [key ]
292
306
if not isinstance (current_idx , tuple ):
@@ -297,7 +311,7 @@ def _raw_append(self, key: Key, item: Item) -> None:
297
311
raise KeyAlreadyPresent (key )
298
312
299
313
self ._map [key ] = current_idx + (len (self ._body ),)
300
- else :
314
+ elif key is not None :
301
315
self ._map [key ] = len (self ._body )
302
316
303
317
self ._body .append ((key , item ))
@@ -605,21 +619,8 @@ def __iter__(self) -> Iterator[str]:
605
619
606
620
# Dictionary methods
607
621
def __getitem__ (self , key : Key | str ) -> Item | Container :
608
- if not isinstance (key , Key ):
609
- key = SingleKey (key )
610
-
611
- idx = self ._map .get (key )
612
- if idx is None :
613
- raise NonExistentKey (key )
614
-
615
- if isinstance (idx , tuple ):
616
- # The item we are getting is an out of order table
617
- # so we need a proxy to retrieve the proper objects
618
- # from the parent container
619
- return OutOfOrderTableProxy (self , idx )
620
-
621
- item = self ._body [idx ][1 ]
622
- if item .is_boolean ():
622
+ item = self .item (key )
623
+ if isinstance (item , Item ) and item .is_boolean ():
623
624
return item .value
624
625
625
626
return item
@@ -700,12 +701,18 @@ def _replace_at(
700
701
if isinstance (value , Table ):
701
702
# Insert a cosmetic new line for tables if:
702
703
# - it does not have it yet OR is not followed by one
703
- # - it is not the last item
704
+ # - it is not the last item, or
705
+ # - The table being replaced has a newline
704
706
last , _ = self ._previous_item_with_index ()
705
707
idx = last if idx < 0 else idx
706
708
has_ws = ends_with_whitespace (value )
709
+ replace_has_ws = (
710
+ isinstance (v , Table )
711
+ and v .value .body
712
+ and isinstance (v .value .body [- 1 ][1 ], Whitespace )
713
+ )
707
714
next_ws = idx < last and isinstance (self ._body [idx + 1 ][1 ], Whitespace )
708
- if idx < last and not (next_ws or has_ws ):
715
+ if ( idx < last or replace_has_ws ) and not (next_ws or has_ws ):
709
716
value .append (None , Whitespace ("\n " ))
710
717
711
718
dict .__setitem__ (self , new_key .key , value .value )
@@ -792,11 +799,13 @@ def __init__(self, container: Container, indices: tuple[int]) -> None:
792
799
self ._tables .append (item )
793
800
table_idx = len (self ._tables ) - 1
794
801
for k , v in item .value .body :
795
- self ._internal_container .append (k , v )
802
+ self ._internal_container .append (k , v , validate = False )
796
803
self ._tables_map [k ] = table_idx
797
804
if k is not None :
798
805
dict .__setitem__ (self , k .key , v )
799
806
807
+ self ._internal_container ._validate_out_of_order_table ()
808
+
800
809
def unwrap (self ) -> str :
801
810
return self ._internal_container .unwrap ()
802
811
0 commit comments