apexdevkit 2.1.3__tar.gz → 2.1.4__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.
Files changed (51) hide show
  1. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/PKG-INFO +2 -2
  2. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/__init__.py +1 -1
  3. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/annotation/deprecate.py +3 -3
  4. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/date.py +16 -16
  5. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/fastapi/__init__.py +2 -2
  6. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/fastapi/builder.py +6 -3
  7. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/fastapi/router.py +7 -0
  8. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/fastapi/service.py +5 -3
  9. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/query/generator.py +16 -16
  10. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/__init__.py +5 -8
  11. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/core/__init__.py +4 -8
  12. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/core/database.py +1 -1
  13. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/in_memory/__init__.py +1 -1
  14. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/in_memory/repository.py +4 -1
  15. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/in_memory/store.py +4 -2
  16. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/sql/__init__.py +1 -1
  17. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/sql/connector.py +6 -3
  18. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/sql/field.py +17 -10
  19. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/sql/mssql/repository.py +2 -2
  20. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/sql/mssql/table.py +6 -3
  21. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/sql/sqlite/__init__.py +1 -1
  22. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/sql/sqlite/repository.py +6 -3
  23. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/sql/sqlite/table.py +6 -3
  24. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/server.py +7 -4
  25. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/sync/__init__.py +4 -4
  26. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/sync/observer.py +5 -3
  27. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/sync/source.py +7 -7
  28. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/sync/sync.py +12 -4
  29. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/testing.py +6 -4
  30. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/pyproject.toml +60 -38
  31. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/LICENSE +0 -0
  32. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/README.md +0 -0
  33. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/annotation/__init__.py +0 -0
  34. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/error.py +0 -0
  35. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/fastapi/dependable.py +0 -0
  36. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/fastapi/docs.py +0 -0
  37. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/fastapi/name.py +0 -0
  38. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/fastapi/resource.py +0 -0
  39. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/fastapi/response.py +0 -0
  40. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/fastapi/schema.py +0 -0
  41. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/formatter.py +0 -0
  42. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/key_fn.py +0 -0
  43. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/py.typed +0 -0
  44. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/query/__init__.py +11 -11
  45. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/query/query.py +0 -0
  46. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/core/decorator.py +0 -0
  47. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/core/interface.py +0 -0
  48. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/core/mixin.py +0 -0
  49. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/in_memory/mixin.py +0 -0
  50. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/repository/sql/mssql/__init__.py +1 -1
  51. {apexdevkit-2.1.3 → apexdevkit-2.1.4}/apexdevkit/sync/target.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apexdevkit
3
- Version: 2.1.3
3
+ Version: 2.1.4
4
4
  Summary: Apex Development Tools for python.
5
5
  License-File: LICENSE
6
6
  Author: Apex Dev
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.15
14
14
  Requires-Dist: fastapi
15
15
  Requires-Dist: pydantic
16
16
  Requires-Dist: pymssql (==2.*)
17
- Requires-Dist: pypebbles (==0.3.*)
17
+ Requires-Dist: pypebbles (==0.4.*)
18
18
  Requires-Dist: python-dotenv
19
19
  Requires-Dist: sentry-sdk[fastapi]
20
20
  Requires-Dist: uvicorn
@@ -2,8 +2,8 @@ from dotenv import load_dotenv
2
2
  from fastapi import APIRouter, FastAPI, HTTPException
3
3
 
4
4
  __all__ = [
5
- "FastAPI",
6
5
  "APIRouter",
6
+ "FastAPI",
7
7
  "HTTPException",
8
8
  "load_dotenv",
9
9
  ]
@@ -25,7 +25,7 @@ def deprecated(warning: str) -> Callable[[F], F]:
25
25
  if inspect.isfunction(obj) or inspect.ismethod(obj):
26
26
  return _wrap_function(obj, warning)
27
27
  if inspect.isclass(obj):
28
- return cast(F, _deprecate_class(obj, warning))
28
+ return cast("F", _deprecate_class(obj, warning))
29
29
  raise TypeError(
30
30
  f"Unsupported type for deprecation: {type(obj)}"
31
31
  ) # pragma: no cover
@@ -38,7 +38,7 @@ def _wrap_function[F: Callable[..., Any]](func: F, warning: str) -> F:
38
38
  warn(warning, category=DeprecationWarning, stacklevel=2)
39
39
  return func(*args, **kwargs)
40
40
 
41
- return cast(F, wrapper)
41
+ return cast("F", wrapper)
42
42
 
43
43
 
44
44
  def _deprecate_class(cls: type, warning: str) -> type:
@@ -47,4 +47,4 @@ def _deprecate_class(cls: type, warning: str) -> type:
47
47
  warn(warning, category=DeprecationWarning, stacklevel=2)
48
48
  super().__init__(*args, **kwargs)
49
49
 
50
- return cast(type, DeprecatedClass)
50
+ return cast("type", DeprecatedClass)
@@ -36,28 +36,28 @@ class DateTime:
36
36
  # Date in format of "yyyy-mm-dd"
37
37
  @classmethod
38
38
  def from_date(cls, date: str, time_zone: ZoneInfo | None = None) -> DateTime:
39
- if time_zone is None:
40
- time_zone = ZoneInfo("UTC")
41
-
42
- dt = datetime.strptime(date, "%Y-%m-%d")
43
- dt = dt.replace(tzinfo=time_zone)
44
- timestamp_ms = int(dt.timestamp() * 1000)
45
-
46
- return cls(timestamp_ms=timestamp_ms)
39
+ return cls(
40
+ timestamp_ms=int(
41
+ datetime.strptime(date, "%Y-%m-%d")
42
+ .replace(tzinfo=time_zone or ZoneInfo("UTC"))
43
+ .timestamp()
44
+ * 1000
45
+ )
46
+ )
47
47
 
48
48
  # Date in format of "yyyy-mm-ddTHH:MM:SS"
49
49
  @classmethod
50
50
  def from_date_time(
51
51
  cls, date_time: str, time_zone: ZoneInfo | None = None
52
52
  ) -> DateTime:
53
- if time_zone is None:
54
- time_zone = ZoneInfo("UTC")
55
-
56
- dt = datetime.strptime(date_time, "%Y-%m-%dT%H:%M:%S")
57
- dt = dt.replace(tzinfo=time_zone)
58
- timestamp_ms = int(dt.timestamp() * 1000)
59
-
60
- return cls(timestamp_ms=timestamp_ms)
53
+ return cls(
54
+ timestamp_ms=int(
55
+ datetime.strptime(date_time, "%Y-%m-%dT%H:%M:%S")
56
+ .replace(tzinfo=time_zone or ZoneInfo("UTC"))
57
+ .timestamp()
58
+ * 1000
59
+ )
60
+ )
61
61
 
62
62
  @classmethod
63
63
  def from_timestamp(cls, timestamp: float) -> DateTime:
@@ -5,9 +5,9 @@ from apexdevkit.fastapi.service import RestfulRepository
5
5
 
6
6
  __all__ = [
7
7
  "FastApiBuilder",
8
- "RestfulServiceBuilder",
9
- "inject",
10
8
  "RestfulRepository",
11
9
  "RestfulRouter",
10
+ "RestfulServiceBuilder",
12
11
  "RouterWithHiddenUnderscoreRoutes",
12
+ "inject",
13
13
  ]
@@ -1,9 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from abc import ABC, abstractmethod
4
- from collections.abc import Mapping, MutableSet
5
4
  from dataclasses import dataclass, field
6
- from typing import Any, Protocol, Self
5
+ from typing import TYPE_CHECKING, Any, Protocol, Self
7
6
 
8
7
  from fastapi import APIRouter, FastAPI
9
8
  from fastapi.middleware.cors import CORSMiddleware
@@ -12,7 +11,11 @@ from fastapi.responses import JSONResponse
12
11
  from apexdevkit.annotation import deprecated
13
12
  from apexdevkit.error import ApiError
14
13
  from apexdevkit.fastapi.dependable import DependableBuilder
15
- from apexdevkit.fastapi.service import RestfulService
14
+
15
+ if TYPE_CHECKING:
16
+ from collections.abc import Mapping, MutableSet
17
+
18
+ from apexdevkit.fastapi.service import RestfulService
16
19
 
17
20
 
18
21
  @dataclass
@@ -123,6 +123,7 @@ class RestfulRouter:
123
123
  def with_create_one(
124
124
  self,
125
125
  dependency: Dependency | None = None,
126
+ *,
126
127
  is_documented: bool = True,
127
128
  ) -> Self:
128
129
  self.router.add_api_route(
@@ -147,6 +148,7 @@ class RestfulRouter:
147
148
  def with_read_one(
148
149
  self,
149
150
  dependency: Dependency | None = None,
151
+ *,
150
152
  is_documented: bool = True,
151
153
  ) -> Self:
152
154
  self.router.add_api_route(
@@ -172,6 +174,7 @@ class RestfulRouter:
172
174
  self,
173
175
  query: FluentDict[Any],
174
176
  dependency: Dependency | None = None,
177
+ *,
175
178
  is_documented: bool = True,
176
179
  ) -> Self:
177
180
  self.router.add_api_route(
@@ -196,6 +199,7 @@ class RestfulRouter:
196
199
  def with_read_all(
197
200
  self,
198
201
  dependency: Dependency | None = None,
202
+ *,
199
203
  is_documented: bool = True,
200
204
  ) -> Self:
201
205
  self.router.add_api_route(
@@ -214,6 +218,7 @@ class RestfulRouter:
214
218
  def with_update_one(
215
219
  self,
216
220
  dependency: Dependency | None = None,
221
+ *,
217
222
  is_documented: bool = True,
218
223
  ) -> Self:
219
224
  self.router.add_api_route(
@@ -242,6 +247,7 @@ class RestfulRouter:
242
247
  def with_replace_one(
243
248
  self,
244
249
  dependency: Dependency | None = None,
250
+ *,
245
251
  is_documented: bool = True,
246
252
  ) -> Self:
247
253
  self.router.add_api_route(
@@ -266,6 +272,7 @@ class RestfulRouter:
266
272
  def with_delete_one(
267
273
  self,
268
274
  dependency: Dependency | None = None,
275
+ *,
269
276
  is_documented: bool = True,
270
277
  ) -> Self:
271
278
  self.router.add_api_route(
@@ -3,11 +3,13 @@ from __future__ import annotations
3
3
  from collections.abc import Iterable, Mapping
4
4
  from dataclasses import dataclass
5
5
  from functools import cached_property
6
- from typing import Any
6
+ from typing import TYPE_CHECKING, Any
7
7
 
8
- from apexdevkit.formatter import Formatter
9
8
  from apexdevkit.repository import BruteForceBatch, Entity, Repository
10
- from apexdevkit.repository.core.interface import BatchRepository
9
+
10
+ if TYPE_CHECKING:
11
+ from apexdevkit.formatter import Formatter
12
+ from apexdevkit.repository.core.interface import BatchRepository
11
13
 
12
14
  RawItem = Mapping[str, Any]
13
15
  RawCollection = Iterable[RawItem]
@@ -1,9 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections import defaultdict
4
- from collections.abc import Iterable, Mapping
5
4
  from dataclasses import dataclass, field
6
- from typing import Any, ClassVar, Protocol, TypeVar
5
+ from typing import TYPE_CHECKING, Any, ClassVar, Protocol
7
6
 
8
7
  from apexdevkit.annotation import deprecated
9
8
  from apexdevkit.error import ForbiddenError
@@ -24,44 +23,45 @@ from apexdevkit.query.query import (
24
23
  )
25
24
  from apexdevkit.repository import Database, DatabaseCommand
26
25
 
27
- ItemT = TypeVar("ItemT", covariant=True)
26
+ if TYPE_CHECKING:
27
+ from collections.abc import Iterable, Mapping
28
28
 
29
29
 
30
- class _Loader(Protocol[ItemT]):
31
- def load(self, raw: Mapping[str, Any]) -> ItemT:
30
+ class _Loader[T](Protocol):
31
+ def load(self, raw: Mapping[str, Any]) -> T:
32
32
  pass
33
33
 
34
34
 
35
35
  @dataclass
36
- class DefaultMsSqlFilter[ItemT]:
36
+ class DefaultMsSqlFilter[T]:
37
37
  _database: Database = field(init=False)
38
38
  _query_builder: MsSqlQueryBuilder = field(init=False)
39
39
  _options: QueryOptions = field(init=False)
40
- _formatter: _Loader[ItemT] = field(init=False)
40
+ _formatter: _Loader[T] = field(init=False)
41
41
 
42
- def with_database(self, value: Database) -> DefaultMsSqlFilter[ItemT]:
42
+ def with_database(self, value: Database) -> DefaultMsSqlFilter[T]:
43
43
  self._database = value
44
44
 
45
45
  return self
46
46
 
47
- def with_query_builder(self, value: MsSqlQueryBuilder) -> DefaultMsSqlFilter[ItemT]:
47
+ def with_query_builder(self, value: MsSqlQueryBuilder) -> DefaultMsSqlFilter[T]:
48
48
  self._query_builder = value
49
49
 
50
50
  return self
51
51
 
52
- def with_options(self, value: QueryOptions) -> DefaultMsSqlFilter[ItemT]:
52
+ def with_options(self, value: QueryOptions) -> DefaultMsSqlFilter[T]:
53
53
  self._options = value
54
54
 
55
55
  return self
56
56
 
57
- def with_formatter(self, value: _Loader[ItemT]) -> DefaultMsSqlFilter[ItemT]:
57
+ def with_formatter(self, value: _Loader[T]) -> DefaultMsSqlFilter[T]:
58
58
  self._formatter = value
59
59
 
60
60
  return self
61
61
 
62
- def retrieve(self) -> Iterable[ItemT]:
62
+ def retrieve(self) -> Iterable[T]:
63
63
  if not any(sort.name == "id" for sort in self._options.ordering):
64
- self._options.ordering.append(Sort("id", False))
64
+ self._options.ordering.append(Sort(name="id", is_descending=False))
65
65
 
66
66
  result = self._database.execute(
67
67
  self._query_builder.filter(self._options)
@@ -101,7 +101,7 @@ class DefaultMsSqlAggregate:
101
101
  for aggregation in self._options.aggregations
102
102
  for value in [
103
103
  result[
104
- f"{aggregation.name if aggregation.name else 'general'}"
104
+ f"{aggregation.name or 'general'}"
105
105
  f"_{aggregation.aggregation.value.lower()}"
106
106
  ]
107
107
  ]
@@ -215,7 +215,7 @@ class MsSqlField:
215
215
 
216
216
  return result
217
217
 
218
- def as_order_part(self, is_descending: bool = False) -> str:
218
+ def as_order_part(self, *, is_descending: bool = False) -> str:
219
219
  result = self.name
220
220
 
221
221
  if is_descending:
@@ -278,7 +278,7 @@ class MsSqlOrderGenerator:
278
278
  return f"ORDER BY {clause}"
279
279
 
280
280
  def generate_one(self, item: Sort) -> str:
281
- return self.field_for(item.name).as_order_part(item.is_descending)
281
+ return self.field_for(item.name).as_order_part(is_descending=item.is_descending)
282
282
 
283
283
  def field_for(self, name: str) -> MsSqlField:
284
284
  for f in self.fields:
@@ -19,23 +19,20 @@ from .in_memory import (
19
19
  from .sql import MsSqlRepository, SqliteRepository
20
20
 
21
21
  __all__ = [
22
- "Entity",
23
- # Core
24
22
  "BruteForceBatch",
23
+ "CacheMixin",
25
24
  "Connection",
26
25
  "Connector",
27
26
  "Cursor",
28
27
  "Database",
29
28
  "DatabaseCommand",
30
- "NoRepository",
31
- "Repository",
32
- "RepositoryDecorator",
33
- # In-memory
34
- "CacheMixin",
29
+ "Entity",
35
30
  "InMemoryByteStore",
36
31
  "InMemoryRepository",
37
32
  "KeyValueStore",
38
- # SQL
39
33
  "MsSqlRepository",
34
+ "NoRepository",
35
+ "Repository",
36
+ "RepositoryDecorator",
40
37
  "SqliteRepository",
41
38
  ]
@@ -11,22 +11,18 @@ from .interface import Entity, ItemT, KeyFn, Repository
11
11
  from .mixin import ContainsMixin
12
12
 
13
13
  __all__ = [
14
- # Database
14
+ "BruteForceBatch",
15
15
  "Connection",
16
16
  "ConnectionContextManager",
17
17
  "Connector",
18
+ "ContainsMixin",
18
19
  "Cursor",
19
20
  "Database",
20
21
  "DatabaseCommand",
21
- # Decorator
22
- "RepositoryDecorator",
23
- "BruteForceBatch",
24
- # Interface
25
22
  "Entity",
26
23
  "ItemT",
27
24
  "KeyFn",
28
- "Repository",
29
25
  "NoRepository",
30
- # Mixin
31
- "ContainsMixin",
26
+ "Repository",
27
+ "RepositoryDecorator",
32
28
  ]
@@ -106,6 +106,6 @@ class ConnectionContextManager(AbstractContextManager[Connection]):
106
106
  def __enter__(self) -> Connection:
107
107
  return self.connection
108
108
 
109
- def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
109
+ def __exit__(self, exc_type: object, exc_value: object, traceback: object) -> None:
110
110
  self.connection.cursor().close()
111
111
  self.connection.close()
@@ -4,7 +4,7 @@ from .store import InMemoryByteStore, KeyValueStore
4
4
 
5
5
  __all__ = [
6
6
  "CacheMixin",
7
- "InMemoryRepository",
8
7
  "InMemoryByteStore",
8
+ "InMemoryRepository",
9
9
  "KeyValueStore",
10
10
  ]
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Iterator
4
3
  from contextlib import suppress
5
4
  from dataclasses import dataclass, field
5
+ from typing import TYPE_CHECKING
6
6
 
7
7
  from apexdevkit.error import DoesNotExistError, ExistsError
8
8
  from apexdevkit.key_fn import AttributeKey
@@ -10,6 +10,9 @@ from apexdevkit.repository.core import ContainsMixin, ItemT, KeyFn, Repository
10
10
 
11
11
  from .store import InMemoryByteStore, KeyValueStore
12
12
 
13
+ if TYPE_CHECKING:
14
+ from collections.abc import Iterator
15
+
13
16
 
14
17
  @dataclass(frozen=True)
15
18
  class InMemoryRepository(ContainsMixin, Repository[ItemT]):
@@ -1,11 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Iterable
4
3
  from dataclasses import dataclass, field
5
- from typing import Protocol
4
+ from typing import TYPE_CHECKING, Protocol
6
5
 
7
6
  from apexdevkit.formatter import Formatter, PickleFormatter
8
7
 
8
+ if TYPE_CHECKING:
9
+ from collections.abc import Iterable
10
+
9
11
 
10
12
  class KeyValueStore[ItemT](Protocol): # pragma: no cover
11
13
  def count(self) -> int:
@@ -3,9 +3,9 @@ from .mssql import MsSqlRepository
3
3
  from .sqlite import SqliteRepository
4
4
 
5
5
  __all__ = [
6
+ "MsSqlRepository",
6
7
  "NotNone",
7
8
  "SqlFieldBuilder",
8
9
  "SqlFieldManager",
9
- "MsSqlRepository",
10
10
  "SqliteRepository",
11
11
  ]
@@ -1,16 +1,19 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import sqlite3
4
- from contextlib import AbstractContextManager
5
4
  from dataclasses import dataclass
6
- from typing import Any
5
+ from typing import TYPE_CHECKING, Any
7
6
 
8
7
  import pymssql
9
8
  from pypebbles.runtime import Environment
10
9
 
11
- from apexdevkit.repository import Connection
12
10
  from apexdevkit.repository.core.database import ConnectionContextManager
13
11
 
12
+ if TYPE_CHECKING:
13
+ from contextlib import AbstractContextManager
14
+
15
+ from apexdevkit.repository import Connection
16
+
14
17
 
15
18
  @dataclass(frozen=True)
16
19
  class SqliteFileConnector:
@@ -1,8 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Iterator, Mapping
4
3
  from dataclasses import dataclass, field
5
- from typing import Any
4
+ from typing import TYPE_CHECKING, Any
5
+
6
+ if TYPE_CHECKING:
7
+ from collections.abc import Iterator, Mapping
6
8
 
7
9
 
8
10
  @dataclass(frozen=True)
@@ -26,7 +28,7 @@ class _SqlField:
26
28
  parent_value: Any | None = None
27
29
 
28
30
  is_filter: bool = False
29
- filter_values: list[Any | None | NotNone] = field(default_factory=list)
31
+ filter_values: list[Any | NotNone | None] = field(default_factory=list)
30
32
 
31
33
  is_fixed: bool = False
32
34
  fixed_value: Any | None = None
@@ -48,7 +50,7 @@ class SqlFieldBuilder:
48
50
  _parent_value: Any | None = None
49
51
 
50
52
  _is_filter: bool = False
51
- _filter_values: list[Any | None | NotNone] = field(default_factory=list)
53
+ _filter_values: list[Any | NotNone | None] = field(default_factory=list)
52
54
 
53
55
  _is_fixed: bool = False
54
56
  _fixed_value: Any | None = None
@@ -73,7 +75,7 @@ class SqlFieldBuilder:
73
75
 
74
76
  return self
75
77
 
76
- def in_ordering(self, descending: bool = False) -> SqlFieldBuilder:
78
+ def in_ordering(self, *, descending: bool = False) -> SqlFieldBuilder:
77
79
  self._is_ordered = True
78
80
  self._is_descending = descending
79
81
 
@@ -95,7 +97,7 @@ class SqlFieldBuilder:
95
97
 
96
98
  return self
97
99
 
98
- def as_filter(self, values: list[Any | None | NotNone]) -> SqlFieldBuilder:
100
+ def as_filter(self, values: list[Any | NotNone | None]) -> SqlFieldBuilder:
99
101
  self._is_filter = True
100
102
  self._filter_values = values
101
103
 
@@ -159,12 +161,17 @@ class SqlFieldManager:
159
161
  def __iter__(self) -> Iterator[_SqlField]:
160
162
  yield from self.fields
161
163
 
162
- def where_statement(self, include_id: bool = False, read_id: bool = False) -> str:
164
+ def where_statement(
165
+ self,
166
+ *,
167
+ include_id: bool = False,
168
+ read_id: bool = False,
169
+ ) -> str:
163
170
  statements = [
164
171
  statement
165
172
  for statement in [
166
173
  self._parent_filter(),
167
- self._id_filter(include_id, read_id),
174
+ self._id_filter(include_id=include_id, read_id=read_id),
168
175
  self._general_filters(),
169
176
  ]
170
177
  if statement != ""
@@ -201,7 +208,7 @@ class SqlFieldManager:
201
208
 
202
209
  return ""
203
210
 
204
- def _id_filter(self, include_id: bool, read_id: bool) -> str:
211
+ def _id_filter(self, *, include_id: bool, read_id: bool) -> str:
205
212
  if not include_id:
206
213
  return ""
207
214
 
@@ -237,7 +244,7 @@ class SqlFieldManager:
237
244
  return "(" + " OR ".join(clauses) + ")"
238
245
 
239
246
  def _general_filters(self) -> str:
240
- statements: list[str] = [] + self.custom_filters
247
+ statements: list[str] = [*self.custom_filters]
241
248
  for key in self.fields:
242
249
  if key.is_filter:
243
250
  inner_statements: list[str] = []
@@ -50,7 +50,7 @@ class MsSqlRepository(ContainsMixin, Repository[ItemT]):
50
50
  except OperationalError as e:
51
51
  if "Conversion failed" in str(e):
52
52
  raise DoesNotExistError(item_id) from e
53
- raise e
53
+ raise
54
54
 
55
55
  if not raw:
56
56
  raise DoesNotExistError(item_id)
@@ -66,7 +66,7 @@ class MssqlException:
66
66
  code: int
67
67
  message: str
68
68
 
69
- def __init__(self, e: DatabaseError):
69
+ def __init__(self, e: DatabaseError) -> None:
70
70
  self.code = e.args[0]
71
71
  self.message = e.args[1].decode()
72
72
 
@@ -1,14 +1,17 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Iterable, Mapping
4
3
  from dataclasses import dataclass
5
- from typing import Any
4
+ from typing import TYPE_CHECKING, Any
6
5
 
7
6
  from apexdevkit.error import ExistsError
8
- from apexdevkit.formatter import Formatter
9
7
  from apexdevkit.repository.core import DatabaseCommand
10
8
  from apexdevkit.repository.sql.field import NotNone, SqlFieldManager, _SqlField
11
9
 
10
+ if TYPE_CHECKING:
11
+ from collections.abc import Iterable, Mapping
12
+
13
+ from apexdevkit.formatter import Formatter
14
+
12
15
 
13
16
  class SqlTable[T]: # pragma: no cover
14
17
  def count_all(self) -> DatabaseCommand:
@@ -2,7 +2,7 @@ from .repository import SqliteRepository
2
2
  from .table import SqliteTableBuilder, SqlTable
3
3
 
4
4
  __all__ = [
5
+ "SqlTable",
5
6
  "SqliteRepository",
6
7
  "SqliteTableBuilder",
7
- "SqlTable",
8
8
  ]
@@ -1,15 +1,18 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Iterator, Mapping
4
3
  from dataclasses import dataclass, field
5
4
  from sqlite3 import IntegrityError
6
- from typing import Any
5
+ from typing import TYPE_CHECKING, Any
7
6
 
8
7
  from apexdevkit.error import DoesNotExistError
9
8
  from apexdevkit.repository import Database, Repository
10
9
  from apexdevkit.repository.core import ContainsMixin, ItemT
11
10
  from apexdevkit.repository.sql.connector import SqliteFileConnector
12
- from apexdevkit.repository.sql.sqlite.table import SqlTable
11
+
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Iterator, Mapping
14
+
15
+ from apexdevkit.repository.sql.sqlite.table import SqlTable
13
16
 
14
17
 
15
18
  @dataclass(frozen=True, kw_only=True)
@@ -1,14 +1,17 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Iterable, Mapping
4
3
  from dataclasses import dataclass
5
- from typing import Any
4
+ from typing import TYPE_CHECKING, Any
6
5
 
7
6
  from apexdevkit.error import ExistsError
8
- from apexdevkit.formatter import Formatter
9
7
  from apexdevkit.repository.core import DatabaseCommand
10
8
  from apexdevkit.repository.sql.field import NotNone, SqlFieldManager, _SqlField
11
9
 
10
+ if TYPE_CHECKING:
11
+ from collections.abc import Iterable, Mapping
12
+
13
+ from apexdevkit.formatter import Formatter
14
+
12
15
 
13
16
  class SqlTable[T]: # pragma: no cover
14
17
  def count_all(self) -> DatabaseCommand:
@@ -1,16 +1,19 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging.config
4
- from collections.abc import Callable
5
4
  from dataclasses import dataclass, field
6
- from typing import Any
5
+ from typing import TYPE_CHECKING, Any
7
6
 
8
7
  import sentry_sdk
9
8
  import uvicorn
10
9
  from dotenv import load_dotenv
11
- from fastapi import FastAPI
12
10
  from pypebbles.runtime import Environment
13
- from sentry_sdk.types import Event, Hint
11
+
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Callable
14
+
15
+ from fastapi import FastAPI
16
+ from sentry_sdk.types import Event, Hint
14
17
 
15
18
 
16
19
  @dataclass
@@ -4,15 +4,15 @@ from .sync import Sync, SyncProbe
4
4
  from .target import NoTarget, Target, TargetDecorator, TargetFailing
5
5
 
6
6
  __all__ = [
7
- "Sync",
8
- "SyncObserver",
9
- "SyncProbe",
10
7
  "EmptySource",
8
+ "NoTarget",
11
9
  "Source",
12
10
  "SourceDecorator",
13
11
  "SourceFailing",
14
12
  "SourcePreSet",
15
- "NoTarget",
13
+ "Sync",
14
+ "SyncObserver",
15
+ "SyncProbe",
16
16
  "Target",
17
17
  "TargetDecorator",
18
18
  "TargetFailing",
@@ -1,15 +1,17 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Callable
4
3
  from dataclasses import dataclass, field
5
- from typing import Protocol, Self
4
+ from typing import TYPE_CHECKING, Protocol, Self
5
+
6
+ if TYPE_CHECKING:
7
+ from collections.abc import Callable
6
8
 
7
9
 
8
10
  @dataclass(frozen=True)
9
11
  class ObservableSync:
10
12
  observers: list[SyncObserver] = field(default_factory=list)
11
13
 
12
- def attach(self, observer: SyncObserver, when: bool = True) -> Self:
14
+ def attach(self, observer: SyncObserver, *, when: bool = True) -> Self:
13
15
  if when:
14
16
  self.observers.append(observer)
15
17
 
@@ -1,15 +1,15 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Iterable
4
3
  from dataclasses import dataclass, field
5
- from typing import Any, Protocol, TypeVar
4
+ from typing import TYPE_CHECKING, Any, Protocol
6
5
 
7
6
  from apexdevkit.key_fn import AttributeKey, KeyFn
8
7
 
9
- T = TypeVar("T", covariant=True)
8
+ if TYPE_CHECKING:
9
+ from collections.abc import Iterable
10
10
 
11
11
 
12
- class Source(Protocol[T]): # pragma: no cover
12
+ class Source[T](Protocol): # pragma: no cover
13
13
  def absent(self) -> Iterable[T]:
14
14
  pass
15
15
 
@@ -87,19 +87,19 @@ class SourceFailing[T]: # pragma: no cover
87
87
 
88
88
 
89
89
  @dataclass(frozen=True, kw_only=True)
90
- class _FailOnAbsent(SourceDecorator[T]):
90
+ class _FailOnAbsent[T](SourceDecorator[T]):
91
91
  def absent(self) -> Iterable[T]: # pragma: no cover
92
92
  raise RuntimeError("Should not request absent!")
93
93
 
94
94
 
95
95
  @dataclass(frozen=True, kw_only=True)
96
- class _FailOnNew(SourceDecorator[T]):
96
+ class _FailOnNew[T](SourceDecorator[T]):
97
97
  def new(self) -> Iterable[T]: # pragma: no cover
98
98
  raise RuntimeError("Should not request new!")
99
99
 
100
100
 
101
101
  @dataclass(frozen=True, kw_only=True)
102
- class _FailOnUpdate(SourceDecorator[T]):
102
+ class _FailOnUpdate[T](SourceDecorator[T]):
103
103
  def updates(self) -> Iterable[T]: # pragma: no cover
104
104
  raise RuntimeError("Should not request updates!")
105
105
 
@@ -1,8 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Callable, Collection, Iterable
4
3
  from dataclasses import dataclass, field, replace
5
- from typing import Any, Self, TypeVar
4
+ from typing import TYPE_CHECKING, Any, Self, TypeVar
6
5
 
7
6
  from apexdevkit.key_fn import AttributeKey, KeyFn
8
7
 
@@ -10,6 +9,9 @@ from .observer import DefaultLog, ObservableSync
10
9
  from .source import EmptySource, Source, SourceDiscriminator, SourcePreSet
11
10
  from .target import IterableTarget, NoTarget, Target
12
11
 
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Callable, Collection, Iterable
14
+
13
15
  T = TypeVar("T")
14
16
 
15
17
 
@@ -44,7 +46,13 @@ class Sync[T](ObservableSync):
44
46
  def dry(self, *, when: bool = True) -> Sync[T]:
45
47
  return replace(self, dry_run=when)
46
48
 
47
- def run(self, prune: bool = True, load: bool = True, update: bool = True) -> None:
49
+ def run(
50
+ self,
51
+ *,
52
+ prune: bool = True,
53
+ load: bool = True,
54
+ update: bool = True,
55
+ ) -> None:
48
56
  if prune:
49
57
  self.prune()
50
58
 
@@ -140,7 +148,7 @@ class SyncProbe:
140
148
 
141
149
  is_enabled: bool = True
142
150
 
143
- def disable(self, when: bool) -> SyncProbe:
151
+ def disable(self, *, when: bool) -> SyncProbe:
144
152
  return SyncProbe(source=self.source, is_enabled=not when)
145
153
 
146
154
  def notify(self, using: Callable[[int], None]) -> SyncProbe:
@@ -1,8 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Collection
4
3
  from dataclasses import dataclass, field, replace
5
- from typing import Any, Self
4
+ from typing import TYPE_CHECKING, Any, Self
6
5
 
7
6
  from pypebbles import JsonDict
8
7
  from pypebbles.http import (
@@ -13,12 +12,15 @@ from pypebbles.http import (
13
12
  HttpTransport,
14
13
  )
15
14
 
16
- from apexdevkit.fastapi.name import RestfulName
15
+ if TYPE_CHECKING:
16
+ from collections.abc import Collection
17
+
18
+ from apexdevkit.fastapi.name import RestfulName
17
19
 
18
20
 
19
21
  @dataclass(frozen=True)
20
22
  class RestRequest:
21
- request: HttpRequest = HttpRequest()
23
+ request: HttpRequest = field(default_factory=HttpRequest)
22
24
 
23
25
  def with_params(self, **params: Any) -> RestRequest:
24
26
  return replace(self, request=self.request.with_params(params))
@@ -1,42 +1,41 @@
1
1
  [project]
2
2
  name = "apexdevkit"
3
- version = "2.1.3"
3
+ version = "2.1.4"
4
4
  description = "Apex Development Tools for python."
5
5
  readme = "README.md"
6
6
  authors = [
7
- { name = "Apex Dev", email = "dev@apex.ge" }
7
+ { name = "Apex Dev", email = "dev@apex.ge" },
8
8
  ]
9
- dynamic = ["dependencies"]
10
9
  requires-python = ">=3.12,<4"
10
+ dynamic = [
11
+ "dependencies",
12
+ ]
11
13
 
12
14
  [tool.poetry.dependencies]
13
15
  fastapi = "*"
14
- python-dotenv = "*"
15
- pymssql = "2.*"
16
16
  pydantic = "*"
17
- sentry-sdk = { extras = ["fastapi"], version = "*" }
17
+ pymssql = "2.*"
18
+ pypebbles = "0.4.*"
19
+ python-dotenv = "*"
20
+ sentry-sdk = { extras = [ "fastapi" ], version = "*" }
18
21
  uvicorn = "*"
19
- pypebbles = "0.3.*"
20
22
 
21
23
  [tool.poetry.group.dev.dependencies]
22
- apexcodexpy = "0.7.1"
24
+ apexcodexpy = "0.8.*"
25
+ coverage = "*"
26
+ faker = "*"
23
27
  pytest = "*"
24
28
  pytest-approvaltests = "*"
25
29
  pytest-cov = "*"
26
30
  pytest-env = "*"
27
31
  pytest-recording = "*"
28
- coverage = "*"
29
- faker = "*"
30
32
 
31
- [tool.mypy]
32
- ignore_missing_imports = true
33
- strict = true
34
- exclude = [
35
- "apexdevkit/fastapi/schema.py",
36
- "apexdevkit/fastapi/dependable.py",
37
- ]
38
- show_error_codes = true
39
- pretty = true
33
+ [tool.ruff.lint.per-file-ignores]
34
+ "apexdevkit/fastapi/resource.py" = [ "N803" ]
35
+ "apexdevkit/fastapi/dependable.py" = [ "N806" ]
36
+
37
+ [tool.ruff.lint.mccabe]
38
+ max-complexity = 10
40
39
 
41
40
  [tool.ruff.lint]
42
41
  select = [
@@ -44,40 +43,63 @@ select = [
44
43
  "ARG",
45
44
  "B",
46
45
  "C4",
47
- "PT",
48
- "RSE",
49
- "RET",
50
- "SIM",
51
- "T20",
46
+ "DTZ",
52
47
  "E",
53
- "W",
54
48
  "F",
49
+ "FBT",
50
+ "FLY",
51
+ "FURB",
55
52
  "I",
53
+ "LOG",
56
54
  "N",
55
+ "PERF",
56
+ "PGH",
57
+ "PIE",
58
+ "PL",
59
+ "PT",
60
+ "PTH",
61
+ "PYI",
62
+ "RET",
63
+ "RSE",
64
+ "RUF",
65
+ "SIM",
66
+ "SLF",
67
+ "T20",
68
+ "TCH",
69
+ "TRY",
57
70
  "UP",
71
+ "W",
72
+ ]
73
+ ignore = [
74
+ "PGH",
75
+ "PLR2004",
76
+ "PYI",
77
+ "TRY003",
58
78
  ]
59
79
 
60
- [tool.ruff.lint.per-file-ignores]
61
- "apexdevkit/fastapi/resource.py" = ["N803"]
62
- "apexdevkit/fastapi/dependable.py" = ["N806"]
63
-
80
+ [tool.mypy]
81
+ exclude = [
82
+ "apexdevkit/fastapi/dependable.py",
83
+ "apexdevkit/fastapi/schema.py",
84
+ ]
85
+ ignore_missing_imports = true
86
+ strict = true
87
+ pretty = true
88
+ show_error_codes = true
64
89
 
65
- [tool.ruff.lint.mccabe]
66
- max-complexity = 10
90
+ [tool.pytest]
91
+ env = [
92
+ "ECHO_SERVER=http://localhost:8080",
93
+ ]
67
94
 
68
95
  [tool.coverage.run]
69
- branch = true
70
96
  source = [
71
97
  "apexdevkit",
72
98
  "tests",
73
99
  ]
100
+ branch = true
74
101
 
75
102
  [tool.coverage.report]
76
- skip_empty = true
77
103
  skip_covered = true
104
+ skip_empty = true
78
105
  show_missing = true
79
-
80
- [tool.pytest]
81
- env = [
82
- "ECHO_SERVER=http://localhost:8080",
83
- ]
File without changes
File without changes
@@ -18,20 +18,20 @@ from apexdevkit.query.query import (
18
18
  )
19
19
 
20
20
  __all__ = [
21
- "FooterOptions",
22
- "QueryOptions",
21
+ "Aggregation",
23
22
  "AggregationOption",
24
- "Sort",
25
- "Page",
26
- "Summary",
27
- "NumericValue",
28
- "StringValue",
29
23
  "DateValue",
24
+ "Filter",
25
+ "FooterOptions",
26
+ "Leaf",
30
27
  "ListValue",
31
28
  "NullValue",
32
- "Leaf",
33
- "Operator",
34
- "Filter",
29
+ "NumericValue",
35
30
  "Operation",
36
- "Aggregation",
31
+ "Operator",
32
+ "Page",
33
+ "QueryOptions",
34
+ "Sort",
35
+ "StringValue",
36
+ "Summary",
37
37
  ]
@@ -2,8 +2,8 @@ from .repository import MsSqlRepository, UnknownError
2
2
  from .table import MsSqlTableBuilder, SqlTable
3
3
 
4
4
  __all__ = [
5
- "MsSqlTableBuilder",
6
5
  "MsSqlRepository",
6
+ "MsSqlTableBuilder",
7
7
  "SqlTable",
8
8
  "UnknownError",
9
9
  ]