Coverage for netbox_data_import/transform_regex.py: 100%

27 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-09 20:50 +0000

1# SPDX-License-Identifier: Apache-2.0 

2# SPDX-FileCopyrightText: 2026 Marcin Zieba <marcinpsk@gmail.com> 

3"""Compile transform patterns with the safe regular-expression engine.""" 

4 

5from __future__ import annotations 

6 

7from dataclasses import dataclass 

8from typing import Any, Self 

9 

10import re2 # type: ignore[import-untyped] 

11 

12 

13class TransformPatternError(ValueError): 

14 """A transform pattern uses invalid or unsupported syntax.""" 

15 

16 

17@dataclass(frozen=True) 

18class TransformPattern: 

19 """A compiled transform pattern with engine details kept private.""" 

20 

21 _compiled: Any 

22 

23 @classmethod 

24 def compile(cls, pattern: str) -> Self: 

25 """Compile one pattern without writing parser errors to the server log.""" 

26 options = re2.Options() 

27 options.log_errors = False 

28 try: 

29 return cls(re2.compile(pattern, options=options)) 

30 except re2.error as exc: 

31 detail = exc.args[0] 

32 if isinstance(detail, bytes): 

33 detail = detail.decode(errors="replace") 

34 raise TransformPatternError(str(detail)) from exc 

35 

36 @property 

37 def group_count(self) -> int: 

38 """Return the number of capturing groups in the pattern.""" 

39 return int(self._compiled.groups) 

40 

41 def capture_groups(self, text: str) -> tuple[str | None, ...] | None: 

42 """Return captured values for a full match, or None when the text does not match.""" 

43 match = self._compiled.fullmatch(text) 

44 if match is None: 

45 return None 

46 return tuple(match.groups())