Coverage for src\pqlattice\settings.py: 58%

1 import contextlib

2 from collections.abc import Generator

3 from typing import Literal

4

5 from ._backends._fast import FastBackend

6 from ._backends._native import NativeBackend

7 from ._backends._protocol import BackendInterface

8

9 BackendName = Literal["native", "fast"]

10

11

12 class _Settings:

13 def __init__(self) -> None:

14 self._active_backend_name: BackendName = "native"

15 self._native_backend = NativeBackend()

16 self._fast_backend: FastBackend | None = None

17

18 @property

19 def backend_name(self) -> BackendName:

20 return self._active_backend_name

21

22 @property

23 def backend(self) -> BackendInterface:

24 if self.backend_name == "native":

25 return self._native_backend

26 elif self.backend_name == "fast":

27 if self._fast_backend is None:

28 self._fast_backend = FastBackend()

29 return self._fast_backend

30

31 raise RuntimeError(f"No backend {self.backend_name}")

32

33 def set_backend(self, name: BackendName) -> None:

34 self._active_backend_name = name

35

36

37 _config = _Settings()

38

39

40 def get_backend_name() -> BackendName:

41 return _config.backend_name

42

43

44 def get_backend() -> BackendInterface:

45 return _config.backend

46

47

48 def set_backend(name: BackendName) -> None:

49 _config.set_backend(name)

50

51

52@contextlib.contextmanager

53 def backend(name: BackendName) -> Generator[None, None, None]:

54 """

55 Context manager to temporarily switch the backend.

56

57 Usage:

58 with pq.settings.backend("fpylll"):

59 pq.lattice.lll(B)

60 """

61 previous = _config.backend_name

62 try:

63 set_backend(name)

64 yield

65 finally:

66 set_backend(previous)