"""A class that parses a slice or element of an array."""from__future__importannotations__author__='Paul Landes'fromtypingimportClassVar,Union,Any,Set,Tuple,Iterable,Type,ListfromenumimportEnum,autofrom..utilimportAPIErrorimportre
[docs]classIntegerSelectionError(APIError):"""Raised for errors parsing or working with :class:`.IntegerSelection`. """pass
[docs]classKind(Enum):"""The kind of integer selection provided by :class:`.IntegerSelection`. """single=auto()list=auto()interval=auto()
[docs]classIntegerSelection(object):"""Parses an string that selects integers. These (:obj:`kind`) include: * :obj:`Kind.single`: ``<int>``: a singleton integers * :obj:`Kind.interval`: ``<int>-<int>``: all the integers in the inclusive interval * :obj:`Kind.list`: ``<int>,<int>,...``: a comma separated list (space optional) To use, create it with :meth:`from_string` and use :meth:`tuple`, :meth:`list`, then use as an iterable. """INTERVAL_DELIM:ClassVar[str]=':'_DICTABLE_ATTRIBUTES:ClassVar[Set[str]]={'kind'}_INTEGER_REGEX:ClassVar[re.Pattern]=re.compile(r'^[-]?\d+$')_INTERVAL_REGEX:ClassVar[re.Pattern]=re.compile(r'^(\d+?)'+INTERVAL_DELIM+r'(\d+)$')_LIST_REGEX:ClassVar[re.Pattern]=re.compile(r'^\d+(?:,\s*\d+)+$')
[docs]def__init__(self,raw:str)->IntegerSelection:"""Parse an integer selection from string ``raw``."""v:Any=Noneifself._INTEGER_REGEX.match(raw):v=int(raw)ifvisNone:m:re.Match=self._INTERVAL_REGEX.match(raw)ifmisnotNone:v=int(m.group(1)),int(m.group(2))ifvisNoneandself._LIST_REGEX.match(raw)isnotNone:v=list(map(int,re.split(r'\s*,\s*',raw)))ifvisNone:raiseIntegerSelectionError(f"Bad selection format: '{raw}'")self._select=v
@propertydefselection(self)->Union[int,Tuple[int,int],Tuple[int]]:"""The selection data based on what was parsed in the initializer (see class docs). """returnself._select@propertydefkind(self)->Kind:"""The kind of selection (see class docs)."""returnKind.from_class(type(self.selection))
[docs]defselect(self,arr:Tuple[Any,...])->List[Any,...]:"""Return element(s) ``arr`` based on the :obj:`selection`. """ifself.kind==Kind.single:return[arr[self.selection]]elifself.kind==Kind.interval:returnarr[self.selection[0]:self.selection[1]]else:returnlist(map(lambdai:arr[i],self.selection))