apexdevkit 1.31.1__tar.gz → 1.32.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/PKG-INFO +1 -1
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/key_fn.py +3 -0
- apexdevkit-1.32.1/apexdevkit/sync/__init__.py +19 -0
- apexdevkit-1.32.1/apexdevkit/sync/observer.py +89 -0
- apexdevkit-1.32.1/apexdevkit/sync/source.py +122 -0
- apexdevkit-1.32.1/apexdevkit/sync/sync.py +78 -0
- apexdevkit-1.32.1/apexdevkit/sync/target.py +82 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/pyproject.toml +1 -1
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/LICENSE +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/README.md +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/date.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/environment.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/error.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/fastapi/name.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/fastapi/resource.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/fastapi/router.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/fluent.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/formatter.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/http/httpx/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/http/httpx/client.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/http/httpx/hooks.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/query/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/query/generator.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/query/query.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/core/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/core/database.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/core/decorator.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/core/interface.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/core/mixin.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/core/multi.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/in_memory/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/in_memory/mixin.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/in_memory/repository.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/in_memory/store.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/sql/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/sql/connector.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/sql/field.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/sql/mssql.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/repository/sql/sqlite.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/security/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/security/core.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/security/hashing.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/server.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/testing/fake.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/testing/rest.py +0 -0
- {apexdevkit-1.31.1 → apexdevkit-1.32.1}/apexdevkit/value.py +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .observer import SyncObserver
|
|
2
|
+
from .source import EmptySource, Source, SourceDecorator, SourceFailing, SourcePreSet
|
|
3
|
+
from .sync import Sync, SyncProbe
|
|
4
|
+
from .target import NoTarget, Target, TargetDecorator, TargetFailing
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"Sync",
|
|
8
|
+
"SyncObserver",
|
|
9
|
+
"SyncProbe",
|
|
10
|
+
"EmptySource",
|
|
11
|
+
"Source",
|
|
12
|
+
"SourceDecorator",
|
|
13
|
+
"SourceFailing",
|
|
14
|
+
"SourcePreSet",
|
|
15
|
+
"NoTarget",
|
|
16
|
+
"Target",
|
|
17
|
+
"TargetDecorator",
|
|
18
|
+
"TargetFailing",
|
|
19
|
+
]
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Protocol, Self
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass(frozen=True)
|
|
9
|
+
class ObservableSync:
|
|
10
|
+
observers: list[SyncObserver] = field(default_factory=list)
|
|
11
|
+
|
|
12
|
+
def attach(self, observer: SyncObserver, when: bool = True) -> Self:
|
|
13
|
+
if when:
|
|
14
|
+
self.observers.append(observer)
|
|
15
|
+
|
|
16
|
+
return self
|
|
17
|
+
|
|
18
|
+
def before_prune(self, n_items: int) -> None:
|
|
19
|
+
for observer in self.observers:
|
|
20
|
+
observer.before_prune(n_items)
|
|
21
|
+
|
|
22
|
+
def after_prune(self, n_items: int) -> None:
|
|
23
|
+
_ = n_items
|
|
24
|
+
|
|
25
|
+
for observer in self.observers:
|
|
26
|
+
observer.after_prune()
|
|
27
|
+
|
|
28
|
+
def before_load(self, n_items: int) -> None:
|
|
29
|
+
for observer in self.observers:
|
|
30
|
+
observer.before_load(n_items)
|
|
31
|
+
|
|
32
|
+
def after_load(self, n_items: int) -> None:
|
|
33
|
+
_ = n_items
|
|
34
|
+
|
|
35
|
+
for observer in self.observers:
|
|
36
|
+
observer.after_load()
|
|
37
|
+
|
|
38
|
+
def before_update(self, n_items: int) -> None:
|
|
39
|
+
for observer in self.observers:
|
|
40
|
+
observer.before_update(n_items)
|
|
41
|
+
|
|
42
|
+
def after_update(self, n_items: int) -> None:
|
|
43
|
+
_ = n_items
|
|
44
|
+
|
|
45
|
+
for observer in self.observers:
|
|
46
|
+
observer.after_update()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class SyncObserver(Protocol): # pragma: no cover
|
|
50
|
+
def before_prune(self, n_items: int) -> None:
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
def after_prune(self) -> None:
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
def before_load(self, n_items: int) -> None:
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
def after_load(self) -> None:
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
def before_update(self, n_items: int) -> None:
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
def after_update(self) -> None:
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass(frozen=True)
|
|
70
|
+
class DefaultLog:
|
|
71
|
+
echo: Callable[[str], None] = print
|
|
72
|
+
|
|
73
|
+
def before_prune(self, n_items: int) -> None:
|
|
74
|
+
self.echo(f"Total # of absent items: {n_items}")
|
|
75
|
+
|
|
76
|
+
def after_prune(self) -> None:
|
|
77
|
+
self.echo("Pruning completed")
|
|
78
|
+
|
|
79
|
+
def before_load(self, n_items: int) -> None:
|
|
80
|
+
self.echo(f"Total # of new items: {n_items}")
|
|
81
|
+
|
|
82
|
+
def after_load(self) -> None:
|
|
83
|
+
self.echo("Loading completed")
|
|
84
|
+
|
|
85
|
+
def before_update(self, n_items: int) -> None:
|
|
86
|
+
self.echo(f"Total # of updates: {n_items}")
|
|
87
|
+
|
|
88
|
+
def after_update(self) -> None:
|
|
89
|
+
self.echo("Updating completed")
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Generic, Protocol, TypeVar
|
|
6
|
+
|
|
7
|
+
from apexdevkit.key_fn import AttributeKey, KeyFn
|
|
8
|
+
|
|
9
|
+
T = TypeVar("T")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Source(Protocol): # pragma: no cover
|
|
13
|
+
def absent(self) -> Iterable[T]:
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
def new(self) -> Iterable[T]:
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
def updates(self) -> Iterable[T]:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class EmptySource: # pragma: no cover
|
|
25
|
+
def absent(self) -> Iterable[T]:
|
|
26
|
+
return []
|
|
27
|
+
|
|
28
|
+
def new(self) -> Iterable[T]:
|
|
29
|
+
return []
|
|
30
|
+
|
|
31
|
+
def updates(self) -> Iterable[T]:
|
|
32
|
+
return []
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True, kw_only=True)
|
|
36
|
+
class SourceDecorator: # pragma: no cover
|
|
37
|
+
inner: Source = field(default_factory=EmptySource)
|
|
38
|
+
|
|
39
|
+
def absent(self) -> Iterable[T]:
|
|
40
|
+
return self.inner.absent()
|
|
41
|
+
|
|
42
|
+
def new(self) -> Iterable[T]:
|
|
43
|
+
return self.inner.new()
|
|
44
|
+
|
|
45
|
+
def updates(self) -> Iterable[T]:
|
|
46
|
+
return self.inner.updates()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True, kw_only=True)
|
|
50
|
+
class SourcePreSet(Generic[T]):
|
|
51
|
+
removals: Iterable[T]
|
|
52
|
+
additions: Iterable[T]
|
|
53
|
+
changes: Iterable[T]
|
|
54
|
+
|
|
55
|
+
def absent(self) -> Iterable[T]:
|
|
56
|
+
return self.removals
|
|
57
|
+
|
|
58
|
+
def new(self) -> Iterable[T]:
|
|
59
|
+
return self.additions
|
|
60
|
+
|
|
61
|
+
def updates(self) -> Iterable[T]:
|
|
62
|
+
return self.changes
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class SourceFailing:
|
|
66
|
+
@staticmethod
|
|
67
|
+
def on_everything(using: Source | None = None) -> Source:
|
|
68
|
+
return SourceFailing.on_absent(
|
|
69
|
+
using=SourceFailing.on_new(
|
|
70
|
+
using=SourceFailing.on_update(
|
|
71
|
+
using=using or EmptySource(),
|
|
72
|
+
),
|
|
73
|
+
),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def on_absent(using: Source | None = None) -> Source:
|
|
78
|
+
return SourceFailing.OnAbsent(inner=using or EmptySource())
|
|
79
|
+
|
|
80
|
+
@dataclass(frozen=True, kw_only=True)
|
|
81
|
+
class OnAbsent(SourceDecorator):
|
|
82
|
+
def absent(self) -> Iterable[T]: # pragma: no cover
|
|
83
|
+
raise RuntimeError("Should not request absent!")
|
|
84
|
+
|
|
85
|
+
@staticmethod
|
|
86
|
+
def on_new(using: Source | None = None) -> Source:
|
|
87
|
+
return SourceFailing.OnNew(inner=using or EmptySource())
|
|
88
|
+
|
|
89
|
+
@dataclass(frozen=True, kw_only=True)
|
|
90
|
+
class OnNew(SourceDecorator):
|
|
91
|
+
def new(self) -> Iterable[T]: # pragma: no cover
|
|
92
|
+
raise RuntimeError("Should not request new!")
|
|
93
|
+
|
|
94
|
+
@staticmethod
|
|
95
|
+
def on_update(using: Source | None = None) -> Source:
|
|
96
|
+
return SourceFailing.OnUpdate(inner=using or EmptySource())
|
|
97
|
+
|
|
98
|
+
@dataclass(frozen=True, kw_only=True)
|
|
99
|
+
class OnUpdate(SourceDecorator):
|
|
100
|
+
def updates(self) -> Iterable[T]: # pragma: no cover
|
|
101
|
+
raise RuntimeError("Should not request updates!")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@dataclass(frozen=True, kw_only=True)
|
|
105
|
+
class SourceDiscriminator(Generic[T]):
|
|
106
|
+
current: Iterable[T]
|
|
107
|
+
latest: Iterable[T]
|
|
108
|
+
|
|
109
|
+
key_fn: KeyFn = AttributeKey("id")
|
|
110
|
+
|
|
111
|
+
def absent(self) -> Iterable[T]:
|
|
112
|
+
index = {self.key_fn(item) for item in self.latest}
|
|
113
|
+
|
|
114
|
+
return [item for item in self.current if self.key_fn(item) not in index]
|
|
115
|
+
|
|
116
|
+
def new(self) -> Iterable[T]:
|
|
117
|
+
index = {self.key_fn(item) for item in self.current}
|
|
118
|
+
|
|
119
|
+
return [item for item in self.latest if self.key_fn(item) not in index]
|
|
120
|
+
|
|
121
|
+
def updates(self) -> Iterable[T]:
|
|
122
|
+
return set(self.latest).difference(self.current)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable, Collection, Iterable
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any, Self
|
|
6
|
+
|
|
7
|
+
from .observer import DefaultLog, ObservableSync
|
|
8
|
+
from .source import Source
|
|
9
|
+
from .target import Target
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True, kw_only=True)
|
|
13
|
+
class Sync(ObservableSync):
|
|
14
|
+
source: Source
|
|
15
|
+
target: Target
|
|
16
|
+
|
|
17
|
+
dry_run: bool = False
|
|
18
|
+
|
|
19
|
+
def with_log(self, using: Callable[[str], None]) -> Self:
|
|
20
|
+
return self.attach(DefaultLog(echo=using))
|
|
21
|
+
|
|
22
|
+
def run(self, prune: bool = True, load: bool = True, update: bool = True) -> None:
|
|
23
|
+
if prune:
|
|
24
|
+
self.prune()
|
|
25
|
+
|
|
26
|
+
if load:
|
|
27
|
+
self.load()
|
|
28
|
+
|
|
29
|
+
if update:
|
|
30
|
+
self.update()
|
|
31
|
+
|
|
32
|
+
def prune(self) -> None:
|
|
33
|
+
(
|
|
34
|
+
SyncProbe(source=set(self.source.absent()))
|
|
35
|
+
.disable(when=self.dry_run)
|
|
36
|
+
.notify(using=self.before_prune)
|
|
37
|
+
.send(using=self.target.prune)
|
|
38
|
+
.notify(using=self.after_prune)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def load(self) -> None:
|
|
42
|
+
(
|
|
43
|
+
SyncProbe(source=set(self.source.new()))
|
|
44
|
+
.disable(when=self.dry_run)
|
|
45
|
+
.notify(using=self.before_load)
|
|
46
|
+
.send(using=self.target.load)
|
|
47
|
+
.notify(using=self.after_load)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def update(self) -> None:
|
|
51
|
+
(
|
|
52
|
+
SyncProbe(source=set(self.source.updates()))
|
|
53
|
+
.disable(when=self.dry_run)
|
|
54
|
+
.notify(using=self.before_update)
|
|
55
|
+
.send(using=self.target.renew)
|
|
56
|
+
.notify(using=self.after_update)
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass(frozen=True, kw_only=True)
|
|
61
|
+
class SyncProbe:
|
|
62
|
+
source: Collection[Any]
|
|
63
|
+
|
|
64
|
+
is_enabled: bool = True
|
|
65
|
+
|
|
66
|
+
def disable(self, when: bool) -> SyncProbe:
|
|
67
|
+
return SyncProbe(source=self.source, is_enabled=not when)
|
|
68
|
+
|
|
69
|
+
def notify(self, using: Callable[[int], None]) -> SyncProbe:
|
|
70
|
+
using(len(self.source))
|
|
71
|
+
|
|
72
|
+
return self
|
|
73
|
+
|
|
74
|
+
def send(self, using: Callable[[Iterable[Any]], None]) -> SyncProbe:
|
|
75
|
+
if self.is_enabled and len(self.source) > 0:
|
|
76
|
+
using(self.source)
|
|
77
|
+
|
|
78
|
+
return self
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Protocol, TypeVar
|
|
6
|
+
|
|
7
|
+
T = TypeVar("T")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Target(Protocol): # pragma: no cover
|
|
11
|
+
def prune(self, source: Iterable[T]) -> None:
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
def load(self, source: Iterable[T]) -> None:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
def renew(self, source: Iterable[T]) -> None:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class NoTarget: # pragma: no cover
|
|
22
|
+
def prune(self, source: Iterable[T]) -> None:
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
def load(self, source: Iterable[T]) -> None:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
def renew(self, source: Iterable[T]) -> None:
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True, kw_only=True)
|
|
33
|
+
class TargetDecorator:
|
|
34
|
+
inner: Target = field(default_factory=NoTarget)
|
|
35
|
+
|
|
36
|
+
def prune(self, source: Iterable[T]) -> None:
|
|
37
|
+
self.inner.prune(source)
|
|
38
|
+
|
|
39
|
+
def load(self, source: Iterable[T]) -> None:
|
|
40
|
+
self.inner.load(source)
|
|
41
|
+
|
|
42
|
+
def renew(self, source: Iterable[T]) -> None:
|
|
43
|
+
self.inner.renew(source)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class TargetFailing:
|
|
47
|
+
@staticmethod
|
|
48
|
+
def on_everything(using: Target | None = None) -> Target:
|
|
49
|
+
return TargetFailing.on_prune(
|
|
50
|
+
using=TargetFailing.on_load(
|
|
51
|
+
using=TargetFailing.on_update(
|
|
52
|
+
using=using or NoTarget(),
|
|
53
|
+
),
|
|
54
|
+
),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def on_prune(using: Target | None = None) -> Target:
|
|
59
|
+
return TargetFailing.OnPrune(inner=using or NoTarget())
|
|
60
|
+
|
|
61
|
+
@dataclass(frozen=True, kw_only=True)
|
|
62
|
+
class OnPrune(TargetDecorator):
|
|
63
|
+
def prune(self, source: Iterable[T]) -> None: # pragma: no cover
|
|
64
|
+
raise RuntimeError(source)
|
|
65
|
+
|
|
66
|
+
@staticmethod
|
|
67
|
+
def on_load(using: Target | None = None) -> Target:
|
|
68
|
+
return TargetFailing.OnLoad(inner=using or NoTarget())
|
|
69
|
+
|
|
70
|
+
@dataclass(frozen=True, kw_only=True)
|
|
71
|
+
class OnLoad(TargetDecorator):
|
|
72
|
+
def load(self, source: Iterable[T]) -> None: # pragma: no cover
|
|
73
|
+
raise RuntimeError(source)
|
|
74
|
+
|
|
75
|
+
@staticmethod
|
|
76
|
+
def on_update(using: Target | None = None) -> Target:
|
|
77
|
+
return TargetFailing.OnUpdate(inner=using or NoTarget())
|
|
78
|
+
|
|
79
|
+
@dataclass(frozen=True, kw_only=True)
|
|
80
|
+
class OnUpdate(TargetDecorator):
|
|
81
|
+
def renew(self, source: Iterable[T]) -> None: # pragma: no cover
|
|
82
|
+
raise RuntimeError(source)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|