apexdevkit 1.32.5__tar.gz → 1.32.7__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.32.5 → apexdevkit-1.32.7}/PKG-INFO +1 -1
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/core/decorator.py +8 -9
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/core/interface.py +3 -3
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/sync/source.py +3 -3
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/sync/sync.py +15 -4
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/sync/target.py +21 -17
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/pyproject.toml +1 -1
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/LICENSE +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/README.md +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/date.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/environment.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/error.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/fastapi/name.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/fastapi/resource.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/fastapi/router.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/fluent.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/formatter.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/http/httpx/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/http/httpx/client.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/http/httpx/hooks.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/key_fn.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/query/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/query/generator.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/query/query.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/core/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/core/database.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/core/mixin.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/core/multi.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/in_memory/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/in_memory/mixin.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/in_memory/repository.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/in_memory/store.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/sql/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/sql/connector.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/sql/field.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/sql/mssql.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/repository/sql/sqlite.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/security/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/security/core.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/security/hashing.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/server.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/sync/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/sync/observer.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/testing/fake.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/testing/rest.py +0 -0
- {apexdevkit-1.32.5 → apexdevkit-1.32.7}/apexdevkit/value.py +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from collections.abc import
|
|
1
|
+
from collections.abc import Iterable, Iterator
|
|
2
2
|
from contextlib import suppress
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
4
|
|
|
@@ -58,19 +58,18 @@ class RepositoryDecorator(Repository[ItemT]): # pragma: no cover
|
|
|
58
58
|
|
|
59
59
|
@dataclass(frozen=True, kw_only=True)
|
|
60
60
|
class BruteForceBatch(RepositoryDecorator[ItemT]):
|
|
61
|
-
def load(self, source:
|
|
61
|
+
def load(self, source: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
62
62
|
for item in source:
|
|
63
63
|
with suppress(ExistsError):
|
|
64
64
|
yield self.inner.create(item)
|
|
65
65
|
|
|
66
|
-
def prune(self, source:
|
|
67
|
-
for item in
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
yield item
|
|
66
|
+
def prune(self, source: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
67
|
+
for item in source:
|
|
68
|
+
with suppress(DoesNotExistError):
|
|
69
|
+
self.inner.delete(item.id)
|
|
70
|
+
yield item
|
|
72
71
|
|
|
73
|
-
def renew(self, source:
|
|
72
|
+
def renew(self, source: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
74
73
|
for item in source:
|
|
75
74
|
with suppress(DoesNotExistError):
|
|
76
75
|
self.inner.update(item)
|
|
@@ -35,11 +35,11 @@ class Repository(Collection[ItemT], Protocol[ItemT]): # pragma: no cover
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
class BatchRepository(Repository[ItemT], Protocol[ItemT]): # pragma: no cover
|
|
38
|
-
def load(self, source:
|
|
38
|
+
def load(self, source: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
39
39
|
pass
|
|
40
40
|
|
|
41
|
-
def prune(self, source:
|
|
41
|
+
def prune(self, source: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
42
42
|
pass
|
|
43
43
|
|
|
44
|
-
def renew(self, source:
|
|
44
|
+
def renew(self, source: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
45
45
|
pass
|
|
@@ -48,9 +48,9 @@ class SourceDecorator(Generic[T]): # pragma: no cover
|
|
|
48
48
|
|
|
49
49
|
@dataclass(frozen=True, kw_only=True)
|
|
50
50
|
class SourcePreSet(Generic[T]):
|
|
51
|
-
removals: Iterable[T]
|
|
52
|
-
additions: Iterable[T]
|
|
53
|
-
changes: Iterable[T]
|
|
51
|
+
removals: Iterable[T] = field(default_factory=list)
|
|
52
|
+
additions: Iterable[T] = field(default_factory=list)
|
|
53
|
+
changes: Iterable[T] = field(default_factory=list)
|
|
54
54
|
|
|
55
55
|
def absent(self) -> Iterable[T]:
|
|
56
56
|
return self.removals
|
|
@@ -5,8 +5,8 @@ from dataclasses import dataclass, field, replace
|
|
|
5
5
|
from typing import Any, Generic, Self, TypeVar
|
|
6
6
|
|
|
7
7
|
from .observer import DefaultLog, ObservableSync
|
|
8
|
-
from .source import EmptySource, Source
|
|
9
|
-
from .target import NoTarget, Target
|
|
8
|
+
from .source import EmptySource, Source, SourcePreSet
|
|
9
|
+
from .target import IterableTarget, NoTarget, Target
|
|
10
10
|
|
|
11
11
|
T = TypeVar("T")
|
|
12
12
|
|
|
@@ -36,6 +36,13 @@ class Sync(ObservableSync, Generic[T]):
|
|
|
36
36
|
def dry(self, *, when: bool = True) -> Sync[T]:
|
|
37
37
|
return replace(self, dry_run=when)
|
|
38
38
|
|
|
39
|
+
def purge(self, target: IterableTarget[T]) -> None:
|
|
40
|
+
(
|
|
41
|
+
self.with_target(target)
|
|
42
|
+
.and_source(SourcePreSet[T](removals=target))
|
|
43
|
+
.run(load=False, update=False)
|
|
44
|
+
)
|
|
45
|
+
|
|
39
46
|
def run(self, prune: bool = True, load: bool = True, update: bool = True) -> None:
|
|
40
47
|
if prune:
|
|
41
48
|
self.prune()
|
|
@@ -88,8 +95,12 @@ class SyncProbe:
|
|
|
88
95
|
|
|
89
96
|
return self
|
|
90
97
|
|
|
91
|
-
def send(self, using: Callable[[Iterable[Any]], None]) -> SyncProbe:
|
|
98
|
+
def send(self, using: Callable[[Iterable[Any]], Iterable[Any] | None]) -> SyncProbe:
|
|
99
|
+
result = None
|
|
92
100
|
if self.is_enabled and len(self.source) > 0:
|
|
93
|
-
using(self.source)
|
|
101
|
+
result = using(self.source)
|
|
102
|
+
|
|
103
|
+
if result:
|
|
104
|
+
list(result)
|
|
94
105
|
|
|
95
106
|
return self
|
|
@@ -2,30 +2,34 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from collections.abc import Iterable
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Generic, Protocol, TypeVar
|
|
6
6
|
|
|
7
|
-
T = TypeVar("T"
|
|
7
|
+
T = TypeVar("T")
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class Target(Protocol[T]): # pragma: no cover
|
|
11
|
-
def prune(self, source: Iterable[T]) ->
|
|
11
|
+
def prune(self, source: Iterable[T]) -> Iterable[T] | None:
|
|
12
12
|
pass
|
|
13
13
|
|
|
14
|
-
def load(self, source: Iterable[T]) ->
|
|
14
|
+
def load(self, source: Iterable[T]) -> Iterable[T] | None:
|
|
15
15
|
pass
|
|
16
16
|
|
|
17
|
-
def renew(self, source: Iterable[T]) ->
|
|
17
|
+
def renew(self, source: Iterable[T]) -> Iterable[T] | None:
|
|
18
18
|
pass
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
class IterableTarget(Target[T], Iterable[T], Protocol[T]):
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
21
25
|
class NoTarget(Generic[T]): # pragma: no cover
|
|
22
|
-
def prune(self, source: Iterable[T]) ->
|
|
26
|
+
def prune(self, source: Iterable[T]) -> Iterable[T] | None:
|
|
23
27
|
pass
|
|
24
28
|
|
|
25
|
-
def load(self, source: Iterable[T]) ->
|
|
29
|
+
def load(self, source: Iterable[T]) -> Iterable[T] | None:
|
|
26
30
|
pass
|
|
27
31
|
|
|
28
|
-
def renew(self, source: Iterable[T]) ->
|
|
32
|
+
def renew(self, source: Iterable[T]) -> Iterable[T] | None:
|
|
29
33
|
pass
|
|
30
34
|
|
|
31
35
|
|
|
@@ -33,14 +37,14 @@ class NoTarget(Generic[T]): # pragma: no cover
|
|
|
33
37
|
class TargetDecorator(Generic[T]):
|
|
34
38
|
inner: Target[T] = field(default_factory=NoTarget)
|
|
35
39
|
|
|
36
|
-
def prune(self, source: Iterable[T]) ->
|
|
37
|
-
self.inner.prune(source)
|
|
40
|
+
def prune(self, source: Iterable[T]) -> Iterable[T] | None:
|
|
41
|
+
return self.inner.prune(source)
|
|
38
42
|
|
|
39
|
-
def load(self, source: Iterable[T]) ->
|
|
40
|
-
self.inner.load(source)
|
|
43
|
+
def load(self, source: Iterable[T]) -> Iterable[T] | None:
|
|
44
|
+
return self.inner.load(source)
|
|
41
45
|
|
|
42
|
-
def renew(self, source: Iterable[T]) ->
|
|
43
|
-
self.inner.renew(source)
|
|
46
|
+
def renew(self, source: Iterable[T]) -> Iterable[T] | None:
|
|
47
|
+
return self.inner.renew(source)
|
|
44
48
|
|
|
45
49
|
|
|
46
50
|
class TargetFailing(Generic[T]):
|
|
@@ -69,17 +73,17 @@ class TargetFailing(Generic[T]):
|
|
|
69
73
|
|
|
70
74
|
@dataclass(frozen=True, kw_only=True)
|
|
71
75
|
class _FailOnPrune(TargetDecorator[T]):
|
|
72
|
-
def prune(self, source: Iterable[T]) ->
|
|
76
|
+
def prune(self, source: Iterable[T]) -> Iterable[T] | None: # pragma: no cover
|
|
73
77
|
raise RuntimeError(source)
|
|
74
78
|
|
|
75
79
|
|
|
76
80
|
@dataclass(frozen=True, kw_only=True)
|
|
77
81
|
class _FailOnLoad(TargetDecorator[T]):
|
|
78
|
-
def load(self, source: Iterable[T]) ->
|
|
82
|
+
def load(self, source: Iterable[T]) -> Iterable[T] | None: # pragma: no cover
|
|
79
83
|
raise RuntimeError(source)
|
|
80
84
|
|
|
81
85
|
|
|
82
86
|
@dataclass(frozen=True, kw_only=True)
|
|
83
87
|
class _FailOnUpdate(TargetDecorator[T]):
|
|
84
|
-
def renew(self, source: Iterable[T]) ->
|
|
88
|
+
def renew(self, source: Iterable[T]) -> Iterable[T] | None: # pragma: no cover
|
|
85
89
|
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
|
|
File without changes
|