Selfie
Loading...
Searching...
No Matches
Lens.py
Go to the documentation of this file.
1import re
2from abc import ABC, abstractmethod
3from collections.abc import Iterator
4from typing import Callable, Generic, Optional, Protocol, TypeVar, Union
5
6from .Snapshot import Snapshot, SnapshotValue
7
8T = TypeVar("T")
9
10
11class Lens(Protocol):
12 def __call__(self, snapshot: Snapshot) -> Snapshot:
13 raise NotImplementedError
14
15
17 def __init__(self):
18 self.lenses: list[Lens] = []
19
20 def __call__(self, snapshot: Snapshot) -> Snapshot:
21 current = snapshot
22 for lens in self.lenses:
23 current = lens(current)
24 return current
25
26 def add(self, lens: Lens) -> "CompoundLens":
27 self.lenses.append(lens)
28 return self
29
31 self, perString: Callable[[str], Optional[str]]
32 ) -> "CompoundLens":
33 def _mutate_each(snapshot: Snapshot) -> Iterator[tuple[str, SnapshotValue]]:
34 for entry in snapshot.items():
35 if entry[1].is_binary:
36 yield entry
37 else:
38 mapped = perString(entry[1].value_string())
39 if mapped is not None:
40 yield (entry[0], SnapshotValue.of(mapped))
41
42 return self.add(lambda snapshot: Snapshot.of_items(_mutate_each(snapshot)))
43
44 def replace_all(self, toReplace: str, replacement: str) -> "CompoundLens":
45 return self.mutate_all_facets(lambda s: s.replace(toReplace, replacement))
46
48 self, pattern: Union[str, re.Pattern[str]], replacement: str
49 ) -> "CompoundLens":
50 return self.mutate_all_facets(lambda s: re.sub(pattern, replacement, s))
51
53 self, target: str, source: str, function: Callable[[str], Optional[str]]
54 ) -> "CompoundLens":
55 def _set_facet_from(snapshot: Snapshot) -> Snapshot:
56 source_value = snapshot.subject_or_facet_maybe(source)
57 if source_value is None:
58 return snapshot
59 else:
60 return self.__set_facet_of(
61 snapshot, target, function(source_value.value_string())
62 )
63
64 return self.add(_set_facet_from)
65
66 def __set_facet_of(
67 self, snapshot: Snapshot, target: str, new_value: Optional[str]
68 ) -> Snapshot:
69 if new_value is None:
70 return snapshot
71 else:
72 return snapshot.plus_or_replace(target, SnapshotValue.of(new_value))
73
75 self, target: str, function: Callable[[str], Optional[str]]
76 ) -> "CompoundLens":
77 return self.set_facet_from(target, target, function)
78
79
80class Camera(Generic[T], ABC):
81 @abstractmethod
82 def snapshot(self, subject: T) -> Snapshot:
83 pass
84
85 def with_lens(self, lens: Lens) -> "Camera[T]":
86 parent = self
87
88 class WithLensCamera(Camera):
89 def snapshot(self, subject: T) -> Snapshot:
90 return lens(parent.snapshot(subject))
91
92 return WithLensCamera()
93
94 @staticmethod
95 def of(lambda_func: Callable[[T], Snapshot]) -> "Camera[T]":
96 class LambdaCamera(Camera):
97 def snapshot(self, subject: T) -> Snapshot:
98 return lambda_func(subject)
99
100 return LambdaCamera()
Snapshot snapshot(self, T subject)
Definition Lens.py:82
"Camera[T]" of(Callable[[T], Snapshot] lambda_func)
Definition Lens.py:95
"Camera[T]" with_lens(self, Lens lens)
Definition Lens.py:85
"CompoundLens" replace_all_regex(self, Union[str, re.Pattern[str]] pattern, str replacement)
Definition Lens.py:49
"CompoundLens" replace_all(self, str toReplace, str replacement)
Definition Lens.py:44
Snapshot __call__(self, Snapshot snapshot)
Definition Lens.py:20
"CompoundLens" mutate_facet(self, str target, Callable[[str], Optional[str]] function)
Definition Lens.py:76
"CompoundLens" add(self, Lens lens)
Definition Lens.py:26
"CompoundLens" mutate_all_facets(self, Callable[[str], Optional[str]] perString)
Definition Lens.py:32
Snapshot __set_facet_of(self, Snapshot snapshot, str target, Optional[str] new_value)
Definition Lens.py:68
"CompoundLens" set_facet_from(self, str target, str source, Callable[[str], Optional[str]] function)
Definition Lens.py:54
Snapshot __call__(self, Snapshot snapshot)
Definition Lens.py:12