Coverage for install/scipp/format/_parse.py: 23%
44 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-04-28 01:28 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-04-28 01:28 +0000
1# SPDX-License-Identifier: BSD-3-Clause
2# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3# @author Jan-Lukas Wynen
5import dataclasses
6import enum
7import re
8from typing import Optional
11def _dataclass_with_slots(**kwargs):
12 try:
13 return dataclasses.dataclass(slots=True, **kwargs)
14 except TypeError:
15 # Fallback for Python < 3.10
16 return dataclasses.dataclass(**kwargs)
19class FormatType(enum.Enum):
20 default = None
21 compact = 'c'
24@_dataclass_with_slots(frozen=True)
25class FormatSpec:
26 format_type: FormatType
27 _selection: Optional[str]
28 _length: Optional[int]
29 _nested: Optional[str]
31 @property
32 def selection(self) -> str:
33 return '^' if self._selection is None else self._selection
35 @property
36 def length(self) -> int:
37 return 4 if self._length is None else int(self._length)
39 @property
40 def nested(self) -> str:
41 return '' if self._nested is None else self._nested
43 @property
44 def has_selection(self) -> bool:
45 return self._selection is not None
47 @property
48 def has_length(self) -> bool:
49 return self._length is not None
51 @property
52 def has_nested(self) -> bool:
53 return self._nested is not None
55 def __str__(self) -> str:
56 return (
57 self.selection
58 if self.has_selection
59 else '' + f'#{self.length}'
60 if self.has_length
61 else '' + str(self.format_type)
62 if self.format_type != FormatType.default
63 else '' + f':{self.nested}'
64 if self.has_nested
65 else ''
66 )
69_FORMAT_PATTERN = re.compile(
70 '^(?P<selection>[><^])?'
71 r'(?:#(?P<length>\d+))?'
72 '(?P<type>[c])?'
73 '(?::(?P<nested>.*))?$'
74)
77def parse(raw_spec: str, cls: type) -> FormatSpec:
78 match = _FORMAT_PATTERN.match(raw_spec)
79 if match is None:
80 raise ValueError(f"Invalid format spec '{raw_spec}' for type '{cls}'")
82 return FormatSpec(
83 format_type=FormatType(match['type']),
84 _selection=match['selection'],
85 _length=match['length'],
86 _nested=match['nested'],
87 )