apexdevkit 1.23.1__tar.gz → 1.23.3__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.23.1 → apexdevkit-1.23.3}/PKG-INFO +1 -1
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/annotation/deprecate.py +4 -5
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fastapi/builder.py +1 -1
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/formatter.py +1 -1
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/id.py +2 -2
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/repository/connector.py +6 -6
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/repository/in_memory.py +17 -3
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/repository/mssql.py +3 -5
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/repository/repository.py +3 -3
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/repository/sql.py +11 -12
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/repository/sqlite.py +3 -3
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/pyproject.toml +15 -2
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/LICENSE +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/README.md +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/environment.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/error.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fastapi/name.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fastapi/request.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fastapi/resource.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fastapi/router.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/fluent.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/http/httpx/__init__.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/http/httpx/client.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/http/httpx/hooks.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/key_fn.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/query/__init__.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/query/generator.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/query/query.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/repository/__init__.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/repository/base.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/repository/database.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/repository/decorator.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/repository/interface.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/server.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/synchronization.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/testing/fake.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/testing/rest.py +0 -0
- {apexdevkit-1.23.1 → apexdevkit-1.23.3}/apexdevkit/value.py +0 -0
|
@@ -24,12 +24,11 @@ def deprecated(warning: str) -> Callable[[F], F]:
|
|
|
24
24
|
def decorator(obj: F) -> F:
|
|
25
25
|
if inspect.isfunction(obj) or inspect.ismethod(obj):
|
|
26
26
|
return cast(F, _wrap_function(obj, warning))
|
|
27
|
-
|
|
27
|
+
if inspect.isclass(obj):
|
|
28
28
|
return cast(F, _deprecate_class(obj, warning))
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
) # pragma: no cover
|
|
29
|
+
raise TypeError(
|
|
30
|
+
f"Unsupported type for deprecation: {type(obj)}"
|
|
31
|
+
) # pragma: no cover
|
|
33
32
|
|
|
34
33
|
return decorator
|
|
35
34
|
|
|
@@ -20,7 +20,7 @@ class FastApiBuilder:
|
|
|
20
20
|
def build(self) -> FastAPI:
|
|
21
21
|
self.app.add_exception_handler(
|
|
22
22
|
ApiError,
|
|
23
|
-
lambda
|
|
23
|
+
lambda _, exc: JSONResponse(content=exc.data, status_code=exc.code),
|
|
24
24
|
)
|
|
25
25
|
return self.app
|
|
26
26
|
|
|
@@ -95,7 +95,7 @@ class DataclassFormatter(Generic[_TargetT]):
|
|
|
95
95
|
key_type = types[key.name]
|
|
96
96
|
if key.name not in raw:
|
|
97
97
|
continue
|
|
98
|
-
|
|
98
|
+
if key.name in self.sub_formatters:
|
|
99
99
|
raw[key.name] = (
|
|
100
100
|
self.sub_formatters[key.name].load(raw.pop(key.name))
|
|
101
101
|
if raw[key.name]
|
|
@@ -30,7 +30,7 @@ class ApexID:
|
|
|
30
30
|
cls.sequence = 0
|
|
31
31
|
|
|
32
32
|
if cls.sequence > cls._sequence_bitmask:
|
|
33
|
-
raise
|
|
33
|
+
raise DuplicateIDError("Duplicate ID Generated")
|
|
34
34
|
|
|
35
35
|
cls.last_timestamp = current_timestamp
|
|
36
36
|
|
|
@@ -50,5 +50,5 @@ class ApexID:
|
|
|
50
50
|
return int(os.getenv("APEX_ID_METADATA", "0"))
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
class
|
|
53
|
+
class DuplicateIDError(Exception):
|
|
54
54
|
pass
|
|
@@ -96,16 +96,16 @@ class MsSqlCursorAdapter:
|
|
|
96
96
|
cursor: Cursor
|
|
97
97
|
|
|
98
98
|
def execute(self, *args: Any, **kwargs: Any) -> Any:
|
|
99
|
-
self.cursor.execute(*args, **kwargs)
|
|
99
|
+
self.cursor.execute(*args, **kwargs)
|
|
100
100
|
|
|
101
101
|
def executemany(self, *args: Any, **kwargs: Any) -> Any:
|
|
102
|
-
self.cursor.executemany(*args, **kwargs)
|
|
102
|
+
self.cursor.executemany(*args, **kwargs)
|
|
103
103
|
|
|
104
|
-
def fetchone(self, *
|
|
105
|
-
return self.cursor.fetchone()
|
|
104
|
+
def fetchone(self, *_: Any, **__: Any) -> Any:
|
|
105
|
+
return self.cursor.fetchone()
|
|
106
106
|
|
|
107
|
-
def fetchall(self, *
|
|
108
|
-
return self.cursor.fetchall()
|
|
107
|
+
def fetchall(self, *_: Any, **__: Any) -> Any:
|
|
108
|
+
return self.cursor.fetchall()
|
|
109
109
|
|
|
110
110
|
def close(self) -> None:
|
|
111
111
|
self.cursor.close() # type : ignore
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from collections
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from collections.abc import Callable, Iterable, Iterator, MutableMapping
|
|
4
5
|
from contextlib import suppress
|
|
5
6
|
from dataclasses import dataclass, field
|
|
6
7
|
from typing import Any, Generic, Protocol, Self
|
|
@@ -102,13 +103,26 @@ class InMemoryByteStore(Generic[ItemT]):
|
|
|
102
103
|
for raw in self.items.values():
|
|
103
104
|
yield self.formatter.load(raw)
|
|
104
105
|
|
|
106
|
+
@dataclass
|
|
107
|
+
class Cache:
|
|
108
|
+
items: MutableMapping[str, InMemoryByteStore[Any]] = field(init=False)
|
|
109
|
+
|
|
110
|
+
def __post_init__(self) -> None:
|
|
111
|
+
self.items = defaultdict(InMemoryByteStore)
|
|
112
|
+
|
|
113
|
+
def store_for(self, name: str) -> InMemoryByteStore[Any]:
|
|
114
|
+
return self.items[name]
|
|
115
|
+
|
|
116
|
+
def clear(self) -> None:
|
|
117
|
+
self.items.clear()
|
|
118
|
+
|
|
105
119
|
|
|
106
120
|
@dataclass
|
|
107
121
|
class _SingleKeyRepository(RepositoryBase[ItemT]):
|
|
108
122
|
store: KeyValueStore[ItemT]
|
|
109
123
|
pk: _KeyFunction[ItemT]
|
|
110
124
|
|
|
111
|
-
def bind(self, **
|
|
125
|
+
def bind(self, **_: Any) -> Self: # pragma: no cover
|
|
112
126
|
return self
|
|
113
127
|
|
|
114
128
|
def create(self, item: ItemT) -> ItemT:
|
|
@@ -154,7 +168,7 @@ class _ManyKeyRepository(RepositoryBase[ItemT]):
|
|
|
154
168
|
|
|
155
169
|
keys: list[_KeyFunction[ItemT]] = field(default_factory=list)
|
|
156
170
|
|
|
157
|
-
def bind(self, **
|
|
171
|
+
def bind(self, **_: Any) -> Self: # pragma: no cover
|
|
158
172
|
return self
|
|
159
173
|
|
|
160
174
|
def create(self, item: ItemT) -> ItemT:
|
|
@@ -52,8 +52,7 @@ class MsSqlRepository(RepositoryBase[ItemT]):
|
|
|
52
52
|
except OperationalError as e:
|
|
53
53
|
if "Conversion failed" in str(e):
|
|
54
54
|
raise DoesNotExistError(item_id) from e
|
|
55
|
-
|
|
56
|
-
raise e
|
|
55
|
+
raise e
|
|
57
56
|
|
|
58
57
|
if not raw:
|
|
59
58
|
raise DoesNotExistError(item_id)
|
|
@@ -367,12 +366,11 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
367
366
|
def exists(self, duplicate: ItemT) -> ExistsError:
|
|
368
367
|
raw = self.formatter.dump(duplicate)
|
|
369
368
|
return ExistsError(duplicate).with_duplicate(
|
|
370
|
-
lambda
|
|
369
|
+
lambda _: f"{self.fields.id}<{raw[self.fields.id]}>"
|
|
371
370
|
)
|
|
372
371
|
|
|
373
372
|
@property
|
|
374
373
|
def _user_check(self) -> str:
|
|
375
374
|
if self.username is not None:
|
|
376
375
|
return f"EXECUTE AS USER = '{self.username}'"
|
|
377
|
-
|
|
378
|
-
return ""
|
|
376
|
+
return ""
|
|
@@ -75,7 +75,7 @@ class MultipleRepositoryBuilder(Generic[ItemT]):
|
|
|
75
75
|
def with_repository(
|
|
76
76
|
self,
|
|
77
77
|
repository: Repository[ItemT],
|
|
78
|
-
condition: Callable[[ItemT], bool] = lambda
|
|
78
|
+
condition: Callable[[ItemT], bool] = lambda _: True,
|
|
79
79
|
formatter: Formatter[ItemT, ItemT] | None = None,
|
|
80
80
|
id_prefix: str = "",
|
|
81
81
|
) -> MultipleRepositoryBuilder[ItemT]:
|
|
@@ -94,7 +94,7 @@ class MultipleRepositoryBuilder(Generic[ItemT]):
|
|
|
94
94
|
def and_repository(
|
|
95
95
|
self,
|
|
96
96
|
repository: Repository[ItemT],
|
|
97
|
-
condition: Callable[[ItemT], bool] = lambda
|
|
97
|
+
condition: Callable[[ItemT], bool] = lambda _: True,
|
|
98
98
|
formatter: Formatter[ItemT, ItemT] | None = None,
|
|
99
99
|
id_prefix: str = "",
|
|
100
100
|
) -> MultipleRepositoryBuilder[ItemT]:
|
|
@@ -112,7 +112,7 @@ class MultipleRepositoryBuilder(Generic[ItemT]):
|
|
|
112
112
|
@dataclass(frozen=True)
|
|
113
113
|
class _InnerRepository(Generic[ItemT]):
|
|
114
114
|
inner: Repository[ItemT]
|
|
115
|
-
condition: Callable[[ItemT], bool] = lambda
|
|
115
|
+
condition: Callable[[ItemT], bool] = lambda _: True
|
|
116
116
|
formatter: Formatter[ItemT, ItemT] = field(
|
|
117
117
|
default_factory=lambda: NoFormatter[ItemT]()
|
|
118
118
|
)
|
|
@@ -145,8 +145,8 @@ class SqlFieldManager:
|
|
|
145
145
|
]
|
|
146
146
|
if len(ordering) > 0:
|
|
147
147
|
return "ORDER BY " + ", ".join(order_clauses)
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
|
|
149
|
+
return ""
|
|
150
150
|
|
|
151
151
|
def __iter__(self) -> Iterator[_SqlField]:
|
|
152
152
|
yield from self.fields
|
|
@@ -163,8 +163,8 @@ class SqlFieldManager:
|
|
|
163
163
|
]
|
|
164
164
|
if len(statements) > 0:
|
|
165
165
|
return "WHERE " + " AND ".join(statements)
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
|
|
167
|
+
return ""
|
|
168
168
|
|
|
169
169
|
def with_fixed(self, raw: Mapping[str, Any]) -> dict[str, Any]:
|
|
170
170
|
data = dict(raw)
|
|
@@ -185,14 +185,13 @@ class SqlFieldManager:
|
|
|
185
185
|
if result is not None:
|
|
186
186
|
if result.parent_value is None:
|
|
187
187
|
return self.key_formatter.replace("x", result.name) + " IS NULL"
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return ""
|
|
188
|
+
return (
|
|
189
|
+
self.key_formatter.replace("x", result.name)
|
|
190
|
+
+ " = "
|
|
191
|
+
+ self.value_formatter.replace("x", result.name)
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
return ""
|
|
196
195
|
|
|
197
196
|
def _id_filter(self, include_id: bool, read_id: bool) -> str:
|
|
198
197
|
return (
|
|
@@ -61,7 +61,7 @@ class SqliteRepository(RepositoryBase[ItemT]):
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
class SqlTable(Generic[ItemT]): # pragma: no cover
|
|
64
|
-
def bind(self, **
|
|
64
|
+
def bind(self, **_: Any) -> SqlTable[ItemT]:
|
|
65
65
|
return self
|
|
66
66
|
|
|
67
67
|
def count_all(self) -> DatabaseCommand:
|
|
@@ -92,7 +92,7 @@ class SqlTable(Generic[ItemT]): # pragma: no cover
|
|
|
92
92
|
raise NotImplementedError
|
|
93
93
|
|
|
94
94
|
def duplicate(self, item: ItemT) -> ExistsError:
|
|
95
|
-
return ExistsError(item).with_duplicate(lambda
|
|
95
|
+
return ExistsError(item).with_duplicate(lambda _: "Unknown")
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
@dataclass
|
|
@@ -251,7 +251,7 @@ class _DefaultSqlTable(SqlTable[ItemT]):
|
|
|
251
251
|
def duplicate(self, item: ItemT) -> ExistsError:
|
|
252
252
|
raw = self.formatter.dump(item)
|
|
253
253
|
return ExistsError(item).with_duplicate(
|
|
254
|
-
lambda
|
|
254
|
+
lambda _: ",".join(
|
|
255
255
|
[f"{key}<{raw[key]}>" for key in raw if key in self.fields.composite]
|
|
256
256
|
)
|
|
257
257
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "apexdevkit"
|
|
3
|
-
version = "1.23.
|
|
3
|
+
version = "1.23.3"
|
|
4
4
|
description = "Apex Development Tools for python."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -50,15 +50,28 @@ exclude = [
|
|
|
50
50
|
|
|
51
51
|
[tool.ruff.lint]
|
|
52
52
|
select = [
|
|
53
|
+
"A", # flake8-builtins
|
|
54
|
+
"ARG", # flake8-unused-arguments
|
|
53
55
|
"B", # flake8-bugbear
|
|
54
56
|
"C4", # flake8-comprehensions
|
|
57
|
+
"PT", # flake8-pytest-style
|
|
58
|
+
"RSE", # flake8-raise
|
|
59
|
+
"RET", # flake8-return
|
|
60
|
+
"SIM", # flake8-simplify
|
|
61
|
+
"T20", # flake8-print
|
|
55
62
|
"E", # pycodestyle errors
|
|
63
|
+
"W", # pycodestyle warnings
|
|
56
64
|
"F", # pyflakes
|
|
57
65
|
"I", # isort
|
|
66
|
+
"N", # pep8-naming
|
|
58
67
|
"UP", # pyupgrade
|
|
59
|
-
"W", # pycodestyle warnings
|
|
60
68
|
]
|
|
61
69
|
|
|
70
|
+
[tool.ruff.lint.per-file-ignores]
|
|
71
|
+
"apexdevkit/fastapi/resource.py" = ["N803"]
|
|
72
|
+
"apexdevkit/fastapi/dependable.py" = ["N806"]
|
|
73
|
+
|
|
74
|
+
|
|
62
75
|
[tool.ruff.lint.mccabe]
|
|
63
76
|
max-complexity = 10
|
|
64
77
|
|
|
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
|