@@ -133,6 +133,24 @@ def _split_match(match: re.Match, iterable: bool) -> SplitPath:
133133 return tuple (split_path )
134134
135135
136+ def _format_range (range_obj : range ) -> str :
137+ start = range_obj .start
138+ stop = range_obj .stop
139+ step = range_obj .step
140+ if range_obj .start == 0 :
141+ start = ''
142+ if range_obj .stop == sys .maxsize :
143+ stop = ''
144+ if range_obj .step == 1 :
145+ step = ''
146+ if not any ((start , stop , step )):
147+ return '[]'
148+ slice_str = f'{ start } :{ stop } '
149+ if step :
150+ slice_str += f':{ step } '
151+ return f'[{ slice_str } ]'
152+
153+
136154def join (split_path : Iterable [Key ]) -> str :
137155 """inverse of split() -- combine an iterable of keys/indexes into a dotted-path format
138156
@@ -160,8 +178,13 @@ def join(split_path: Iterable[Key]) -> str:
160178 path = f'{ path } []'
161179 else :
162180 path = '[]'
181+ elif isinstance (part , range ):
182+ if path :
183+ path = f'{ path } { _format_range (part )} '
184+ else :
185+ path = _format_range (part )
163186 else :
164- raise ValidationError (f'index { i } is invalid, must be str/int, '
187+ raise ValidationError (f'index { i } is invalid, must be str/int/range/ITERATION_POINT , '
165188 f'got { type (part ).__name__ } ' )
166189 return path
167190
@@ -171,7 +194,7 @@ def _validate_key_collection_type(obj: Collection, key: Key) -> None:
171194 validate a collection object and key are valid and corresponding types
172195 raise a ValidationError if they are not
173196 """
174- if key is ITERATION_POINT :
197+ if key is ITERATION_POINT or isinstance ( key , range ) :
175198 raise TypeError ('bug: iteration not supported here' )
176199 if not isinstance (obj , _collection_types ):
177200 raise TypeValidationError ('object must be list/dict' )
0 commit comments