#!/usr/bin/python
# -*- coding: utf-8 -*-
"""Array slicing module."""
from collections.abc import Sequence
import itertools
import json
from typing import Generator
from jsonpath2.node import MatchData
from jsonpath2.subscript import Subscript
from jsonpath2.subscripts.arrayindex import ArrayIndexSubscript
[docs]class ArraySliceSubscript(Subscript):
"""Array slice class for the parse tree."""
[docs] def __init__(self, start: int = None, end: int = None, step: int = None):
"""Save the start end and step in the array slice."""
super(ArraySliceSubscript, self).__init__()
self.start = start
self.end = end
self.step = step
def __jsonpath__(self) -> Generator[str, None, None]:
"""Return the jsonpath of the array slice."""
if self.start is not None:
yield json.dumps(self.start)
yield ':'
if self.end is not None:
yield json.dumps(self.end)
if self.step is not None:
yield ':'
yield json.dumps(self.step)
[docs] def match(self, root_value: object, current_value: object) -> Generator[MatchData, None, None]:
"""Match an array slice between values."""
if isinstance(current_value, Sequence) and not isinstance(current_value, str):
start = None if (self.start is None) else (
self.start + ((
len(current_value) if abs(self.start) < len(current_value) else abs(self.start)
) if (self.start < 0) else 0))
end = None if (self.end is None) else (
self.end + (len(current_value) if (self.end < 0) else 0))
if start is None:
if end is None:
if self.step is None:
indices = range(0, len(current_value))
else:
indices = range(0, len(current_value), self.step)
else:
if self.step is None:
indices = range(0, end)
else:
indices = range(0, end, self.step)
else:
if end is None:
if self.step is None:
indices = range(start, len(current_value))
else:
indices = range(start, len(current_value), self.step)
else:
if self.step is None:
indices = range(start, end)
else:
indices = range(start, end, self.step)
return itertools.chain(*map(
lambda index: ArrayIndexSubscript(
index).match(root_value, current_value),
indices))
return []