apexdevkit 1.22.2__tar.gz → 1.23.2__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 (54) hide show
  1. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/PKG-INFO +2 -2
  2. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/annotation/deprecate.py +6 -6
  3. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/error.py +2 -1
  4. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fastapi/builder.py +3 -2
  5. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fastapi/dependable.py +3 -2
  6. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fastapi/resource.py +2 -1
  7. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fastapi/response.py +2 -1
  8. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fastapi/schema.py +6 -5
  9. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fastapi/service.py +4 -4
  10. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fluent.py +2 -1
  11. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/formatter.py +3 -4
  12. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/http/fluent.py +5 -5
  13. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/http/httpx/client.py +2 -1
  14. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/id.py +2 -2
  15. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/query/generator.py +2 -1
  16. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/query/query.py +1 -1
  17. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/repository/base.py +2 -1
  18. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/repository/connector.py +11 -11
  19. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/repository/database.py +4 -2
  20. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/repository/decorator.py +2 -1
  21. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/repository/in_memory.py +8 -7
  22. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/repository/interface.py +2 -2
  23. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/repository/mssql.py +12 -15
  24. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/repository/repository.py +21 -8
  25. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/repository/sql.py +13 -13
  26. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/repository/sqlite.py +9 -8
  27. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/server.py +2 -1
  28. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/synchronization.py +2 -1
  29. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/testing/database.py +3 -3
  30. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/testing/fake.py +13 -13
  31. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/testing/rest.py +2 -1
  32. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/pyproject.toml +31 -12
  33. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/LICENSE +0 -0
  34. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/README.md +0 -0
  35. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/__init__.py +0 -0
  36. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/annotation/__init__.py +0 -0
  37. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/environment.py +0 -0
  38. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fastapi/__init__.py +0 -0
  39. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fastapi/docs.py +0 -0
  40. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fastapi/name.py +0 -0
  41. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fastapi/request.py +0 -0
  42. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/fastapi/router.py +0 -0
  43. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/http/__init__.py +0 -0
  44. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/http/fake.py +0 -0
  45. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/http/httpx/__init__.py +0 -0
  46. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/http/httpx/hooks.py +0 -0
  47. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/http/json.py +0 -0
  48. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/http/url.py +0 -0
  49. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/key_fn.py +0 -0
  50. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/py.typed +0 -0
  51. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/query/__init__.py +0 -0
  52. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/repository/__init__.py +0 -0
  53. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/testing/__init__.py +0 -0
  54. {apexdevkit-1.22.2 → apexdevkit-1.23.2}/apexdevkit/value.py +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: apexdevkit
3
- Version: 1.22.2
3
+ Version: 1.23.2
4
4
  Summary: Apex Development Tools for python.
5
5
  Author: Apex Dev
6
6
  Author-email: dev@apex.ge
7
- Requires-Python: >=3.11,<4.0
7
+ Requires-Python: >=3.11
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.11
10
10
  Classifier: Programming Language :: Python :: 3.12
@@ -1,5 +1,6 @@
1
1
  import inspect
2
- from typing import Any, Callable, TypeVar, cast
2
+ from collections.abc import Callable
3
+ from typing import Any, TypeVar, cast
3
4
  from warnings import warn
4
5
 
5
6
  F = TypeVar("F", bound=Callable[..., Any])
@@ -23,12 +24,11 @@ def deprecated(warning: str) -> Callable[[F], F]:
23
24
  def decorator(obj: F) -> F:
24
25
  if inspect.isfunction(obj) or inspect.ismethod(obj):
25
26
  return cast(F, _wrap_function(obj, warning))
26
- elif inspect.isclass(obj):
27
+ if inspect.isclass(obj):
27
28
  return cast(F, _deprecate_class(obj, warning))
28
- else:
29
- raise TypeError(
30
- f"Unsupported type for deprecation: {type(obj)}"
31
- ) # pragma: no cover
29
+ raise TypeError(
30
+ f"Unsupported type for deprecation: {type(obj)}"
31
+ ) # pragma: no cover
32
32
 
33
33
  return decorator
34
34
 
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Callable
3
4
  from dataclasses import dataclass, field
4
- from typing import Any, Callable, Self
5
+ from typing import Any, Self
5
6
 
6
7
  Criteria = Callable[[Any], str]
7
8
 
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from abc import ABC, abstractmethod
4
+ from collections.abc import Mapping
4
5
  from dataclasses import dataclass, field
5
- from typing import Any, Mapping, Self
6
+ from typing import Any, Self
6
7
 
7
8
  from fastapi import APIRouter, FastAPI
8
9
  from starlette.middleware.cors import CORSMiddleware
@@ -19,7 +20,7 @@ class FastApiBuilder:
19
20
  def build(self) -> FastAPI:
20
21
  self.app.add_exception_handler(
21
22
  ApiError,
22
- lambda request, exc: JSONResponse(content=exc.data, status_code=exc.code),
23
+ lambda _, exc: JSONResponse(content=exc.data, status_code=exc.code),
23
24
  )
24
25
  return self.app
25
26
 
@@ -1,5 +1,6 @@
1
+ from collections.abc import Callable
1
2
  from dataclasses import dataclass
2
- from typing import Annotated, Any, Callable, Protocol
3
+ from typing import Annotated, Any, Protocol
3
4
 
4
5
  from fastapi import Depends, Path
5
6
  from fastapi.requests import Request
@@ -52,7 +53,7 @@ class ParentDependency:
52
53
  try:
53
54
  return builder.with_parent(parent_id)
54
55
  except DoesNotExistError as e:
55
- raise ApiError(404, RestfulResponse(self.parent).not_found(e))
56
+ raise ApiError(404, RestfulResponse(self.parent).not_found(e)) from e
56
57
 
57
58
  return Annotated[RestfulServiceBuilder, Depends(_)]
58
59
 
@@ -1,6 +1,7 @@
1
1
  import re
2
+ from collections.abc import Callable
2
3
  from dataclasses import dataclass
3
- from typing import Any, Callable, Union
4
+ from typing import Any, Union
4
5
 
5
6
  from pydantic import BaseModel
6
7
  from starlette.responses import JSONResponse
@@ -1,5 +1,6 @@
1
+ from collections.abc import Iterable
1
2
  from dataclasses import dataclass
2
- from typing import Any, Iterable
3
+ from typing import Any
3
4
 
4
5
  from apexdevkit.error import DoesNotExistError, ExistsError, ForbiddenError
5
6
  from apexdevkit.fastapi.name import RestfulName
@@ -1,7 +1,8 @@
1
1
  from abc import ABC, abstractmethod
2
+ from collections.abc import Callable, Iterable
2
3
  from dataclasses import dataclass
3
4
  from functools import cached_property
4
- from typing import Any, Callable, Iterable, List
5
+ from typing import Any
5
6
 
6
7
  from pydantic import BaseModel, create_model
7
8
 
@@ -39,10 +40,10 @@ class RestfulSchema:
39
40
  )
40
41
 
41
42
  self._schema_for("Item", {self.name.singular: schema})
42
- self._schema_for("Collection", {self.name.plural: List[schema], "count": int})
43
- self._schema_for("CreateMany", {self.name.plural: List[create_schema]})
44
- self._schema_for("UpdateMany", {self.name.plural: List[update_many_item]})
45
- self._schema_for("ReplaceMany", {self.name.plural: List[replace_schema]})
43
+ self._schema_for("Collection", {self.name.plural: list[schema], "count": int})
44
+ self._schema_for("CreateMany", {self.name.plural: list[create_schema]})
45
+ self._schema_for("UpdateMany", {self.name.plural: list[update_many_item]})
46
+ self._schema_for("ReplaceMany", {self.name.plural: list[replace_schema]})
46
47
 
47
48
  def _schema_for(self, action: str, fields: dict[str, Any]) -> type[BaseModel]:
48
49
  if action not in self.schemas:
@@ -1,9 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- from abc import ABC
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, Dict, Generic, Iterable, Mapping, TypeVar
6
+ from typing import Any, Generic, TypeVar
7
7
 
8
8
  from apexdevkit.formatter import Formatter
9
9
  from apexdevkit.query.query import FooterOptions, QueryOptions, Summary
@@ -14,7 +14,7 @@ RawItem = Mapping[str, Any]
14
14
  RawCollection = Iterable[RawItem]
15
15
 
16
16
 
17
- class _RawItemWithId(Dict[str, Any]):
17
+ class _RawItemWithId(dict[str, Any]):
18
18
  def __post_init__(self) -> None:
19
19
  assert "id" in self
20
20
 
@@ -22,7 +22,7 @@ class _RawItemWithId(Dict[str, Any]):
22
22
  RawCollectionWithId = Iterable[_RawItemWithId]
23
23
 
24
24
 
25
- class RestfulService(ABC): # pragma: no cover
25
+ class RestfulService: # pragma: no cover
26
26
  def create_one(self, item: RawItem) -> RawItem:
27
27
  raise NotImplementedError(self.create_one.__name__)
28
28
 
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Callable
3
4
  from dataclasses import dataclass
4
- from typing import Any, Callable, Generic, TypeVar
5
+ from typing import Any, Generic, TypeVar
5
6
 
6
7
  ItemT = TypeVar("ItemT")
7
8
 
@@ -1,11 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import pickle
4
+ from collections.abc import Mapping
4
5
  from copy import deepcopy
5
6
  from dataclasses import asdict, dataclass, field, fields, is_dataclass
6
- from typing import Any, Generic, Mapping, Protocol, Self, TypeVar, get_args
7
-
8
- from typing_extensions import get_type_hints
7
+ from typing import Any, Generic, Protocol, Self, TypeVar, get_args, get_type_hints
9
8
 
10
9
  from apexdevkit.fluent import FluentDict
11
10
  from apexdevkit.value import Value
@@ -96,7 +95,7 @@ class DataclassFormatter(Generic[_TargetT]):
96
95
  key_type = types[key.name]
97
96
  if key.name not in raw:
98
97
  continue
99
- elif key.name in self.sub_formatters.keys():
98
+ if key.name in self.sub_formatters:
100
99
  raw[key.name] = (
101
100
  self.sub_formatters[key.name].load(raw.pop(key.name))
102
101
  if raw[key.name]
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
4
  from enum import Enum, auto
5
- from typing import Any, Protocol, Type
5
+ from typing import Any, Protocol
6
6
 
7
7
  from apexdevkit.http.json import JsonDict
8
8
 
@@ -103,25 +103,25 @@ class FluentHttpRequest:
103
103
  class FluentHttpResponse:
104
104
  response: HttpResponse
105
105
 
106
- def on_bad_request(self, raises: Exception | Type[Exception]) -> FluentHttpResponse:
106
+ def on_bad_request(self, raises: Exception | type[Exception]) -> FluentHttpResponse:
107
107
  if self.response.code() == 400:
108
108
  raise raises
109
109
 
110
110
  return self
111
111
 
112
- def on_conflict(self, raises: Exception | Type[Exception]) -> FluentHttpResponse:
112
+ def on_conflict(self, raises: Exception | type[Exception]) -> FluentHttpResponse:
113
113
  if self.response.code() == 409:
114
114
  raise raises
115
115
 
116
116
  return self
117
117
 
118
- def on_not_found(self, raises: Exception | Type[Exception]) -> FluentHttpResponse:
118
+ def on_not_found(self, raises: Exception | type[Exception]) -> FluentHttpResponse:
119
119
  if self.response.code() == 404:
120
120
  raise raises
121
121
 
122
122
  return self
123
123
 
124
- def on_failure(self, raises: Type[Exception]) -> FluentHttpResponse:
124
+ def on_failure(self, raises: type[Exception]) -> FluentHttpResponse:
125
125
  if self.response.code() < 200 or self.response.code() > 299:
126
126
  raise raises(self.response.raw(), self.response.code())
127
127
 
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Callable, Iterator, Mapping
3
4
  from dataclasses import dataclass, field
4
- from typing import Any, Callable, Iterator, Mapping
5
+ from typing import Any
5
6
 
6
7
  import httpx
7
8
 
@@ -30,7 +30,7 @@ class ApexID:
30
30
  cls.sequence = 0
31
31
 
32
32
  if cls.sequence > cls._sequence_bitmask:
33
- raise DuplicateIDException("Duplicate ID Generated")
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 DuplicateIDException(Exception):
53
+ class DuplicateIDError(Exception):
54
54
  pass
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections import defaultdict
4
+ from collections.abc import Iterable, Mapping
4
5
  from dataclasses import dataclass, field
5
- from typing import Any, ClassVar, Generic, Iterable, Mapping, Protocol, TypeVar
6
+ from typing import Any, ClassVar, Generic, Protocol, TypeVar
6
7
 
7
8
  from apexdevkit.annotation import deprecated
8
9
  from apexdevkit.error import ForbiddenError
@@ -59,7 +59,7 @@ class SummaryExtractor:
59
59
  def _value(self, value: Any) -> NumericValue | DateValue | StringValue | NullValue:
60
60
  if value is None:
61
61
  return NullValue()
62
- if isinstance(value, (int, float, Decimal)):
62
+ if isinstance(value, int | float | Decimal):
63
63
  return NumericValue.from_decimal(Decimal(value))
64
64
  if self.aggregation.name and (
65
65
  "date" in self.aggregation.name.lower()
@@ -1,4 +1,5 @@
1
- from typing import Any, Generic, Iterator
1
+ from collections.abc import Iterator
2
+ from typing import Any, Generic
2
3
 
3
4
  from apexdevkit.repository.interface import ItemT, Repository
4
5
 
@@ -4,7 +4,7 @@ import sqlite3
4
4
  from contextlib import AbstractContextManager
5
5
  from dataclasses import dataclass
6
6
  from functools import cached_property
7
- from typing import Any, ContextManager
7
+ from typing import Any
8
8
 
9
9
  import pymssql
10
10
  from pymssql import Connection as _Connection
@@ -17,7 +17,7 @@ from apexdevkit.repository import Connection
17
17
  class SqliteFileConnector:
18
18
  dsn: str
19
19
 
20
- def connect(self) -> ContextManager[Connection]:
20
+ def connect(self) -> AbstractContextManager[Connection]:
21
21
  connection = sqlite3.connect(self.dsn)
22
22
  connection.row_factory = sqlite3.Row
23
23
 
@@ -28,11 +28,11 @@ class SqliteFileConnector:
28
28
  class SqliteInMemoryConnector:
29
29
  dsn: str = ":memory:"
30
30
 
31
- def connect(self) -> ContextManager[Connection]:
31
+ def connect(self) -> AbstractContextManager[Connection]:
32
32
  return self._connection
33
33
 
34
34
  @cached_property
35
- def _connection(self) -> ContextManager[Connection]:
35
+ def _connection(self) -> AbstractContextManager[Connection]:
36
36
  connection = sqlite3.connect(self.dsn, check_same_thread=False)
37
37
  connection.row_factory = sqlite3.Row
38
38
 
@@ -48,7 +48,7 @@ class MsSqlConnector:
48
48
  db_tds_version = "7.0"
49
49
  db_port: str | None = None
50
50
 
51
- def connect(self) -> ContextManager[Connection]:
51
+ def connect(self) -> AbstractContextManager[Connection]:
52
52
  return ConnectionContextManager(self._connection())
53
53
 
54
54
  def _connection(self) -> Connection:
@@ -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) # type : ignore
99
+ self.cursor.execute(*args, **kwargs)
100
100
 
101
101
  def executemany(self, *args: Any, **kwargs: Any) -> Any:
102
- self.cursor.executemany(*args, **kwargs) # type : ignore
102
+ self.cursor.executemany(*args, **kwargs)
103
103
 
104
- def fetchone(self, *args: Any, **kwargs: Any) -> Any:
105
- return self.cursor.fetchone() # type : ignore
104
+ def fetchone(self, *_: Any, **__: Any) -> Any:
105
+ return self.cursor.fetchone()
106
106
 
107
- def fetchall(self, *args: Any, **kwargs: Any) -> Any:
108
- return self.cursor.fetchall() # type : ignore
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,8 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Iterable, Mapping
4
+ from contextlib import AbstractContextManager
3
5
  from copy import deepcopy
4
6
  from dataclasses import dataclass, field
5
- from typing import Any, ContextManager, Iterable, Mapping, Protocol
7
+ from typing import Any, Protocol
6
8
 
7
9
  _RawData = Mapping[str, Any]
8
10
 
@@ -45,7 +47,7 @@ class Database:
45
47
 
46
48
 
47
49
  class Connector(Protocol): # pragma: no cover
48
- def connect(self) -> ContextManager[Connection]:
50
+ def connect(self) -> AbstractContextManager[Connection]:
49
51
  pass
50
52
 
51
53
 
@@ -1,5 +1,6 @@
1
+ from collections.abc import Iterable, Iterator
1
2
  from dataclasses import dataclass
2
- from typing import Any, Generic, Iterable, Iterator
3
+ from typing import Any, Generic
3
4
 
4
5
  from apexdevkit.repository.interface import ItemT, Repository
5
6
 
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Callable, Iterable, Iterator
3
4
  from contextlib import suppress
4
5
  from dataclasses import dataclass, field
5
- from typing import Any, Callable, Generic, Iterable, Iterator, Protocol, Self
6
+ from typing import Any, Generic, Protocol, Self
6
7
 
7
8
  from apexdevkit.error import DoesNotExistError, ExistsError
8
9
  from apexdevkit.formatter import Formatter, PickleFormatter
@@ -107,7 +108,7 @@ class _SingleKeyRepository(RepositoryBase[ItemT]):
107
108
  store: KeyValueStore[ItemT]
108
109
  pk: _KeyFunction[ItemT]
109
110
 
110
- def bind(self, **kwargs: Any) -> Self: # pragma: no cover
111
+ def bind(self, **_: Any) -> Self: # pragma: no cover
111
112
  return self
112
113
 
113
114
  def create(self, item: ItemT) -> ItemT:
@@ -131,14 +132,14 @@ class _SingleKeyRepository(RepositoryBase[ItemT]):
131
132
  def delete(self, item_id: str) -> None:
132
133
  try:
133
134
  self.store.drop(item_id)
134
- except KeyError:
135
- raise DoesNotExistError(item_id)
135
+ except KeyError as e:
136
+ raise DoesNotExistError(item_id) from e
136
137
 
137
138
  def read(self, item_id: str) -> ItemT:
138
139
  try:
139
140
  return self.store.get(item_id)
140
- except KeyError:
141
- raise DoesNotExistError(item_id)
141
+ except KeyError as e:
142
+ raise DoesNotExistError(item_id) from e
142
143
 
143
144
  def __iter__(self) -> Iterator[ItemT]:
144
145
  return iter(self.store.values())
@@ -153,7 +154,7 @@ class _ManyKeyRepository(RepositoryBase[ItemT]):
153
154
 
154
155
  keys: list[_KeyFunction[ItemT]] = field(default_factory=list)
155
156
 
156
- def bind(self, **kwargs: Any) -> Self: # pragma: no cover
157
+ def bind(self, **_: Any) -> Self: # pragma: no cover
157
158
  return self
158
159
 
159
160
  def create(self, item: ItemT) -> ItemT:
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Iterable
4
- from typing import Any, Iterator, Protocol, TypeVar
3
+ from collections.abc import Iterable, Iterator
4
+ from typing import Any, Protocol, TypeVar
5
5
 
6
6
  ItemT = TypeVar("ItemT")
7
7
 
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Iterable, Iterator, Mapping
3
4
  from dataclasses import dataclass
4
- from typing import Any, Generic, Iterable, Iterator, Mapping, TypeVar
5
+ from typing import Any, Generic, TypeVar
5
6
 
6
7
  from pymssql.exceptions import DatabaseError, OperationalError
7
8
 
@@ -27,8 +28,8 @@ class MsSqlRepository(RepositoryBase[ItemT]):
27
28
 
28
29
  try:
29
30
  return int(raw["n_items"])
30
- except KeyError:
31
- raise UnknownError(raw)
31
+ except KeyError as e:
32
+ raise UnknownError(raw) from e
32
33
 
33
34
  def delete(self, item_id: str) -> None:
34
35
  self.db.execute(self.table.delete(item_id)).fetch_none()
@@ -40,21 +41,18 @@ class MsSqlRepository(RepositoryBase[ItemT]):
40
41
  try:
41
42
  return self.table.load(self.db.execute(self.table.insert(item)).fetch_one())
42
43
  except DatabaseError as e:
43
- e = MssqlException(e)
44
+ if MssqlException(e).is_duplication():
45
+ raise self.table.exists(item) from e
44
46
 
45
- if e.is_duplication():
46
- raise self.table.exists(item)
47
-
48
- raise UnknownError(e.message)
47
+ raise UnknownError(MssqlException(e).message) from e
49
48
 
50
49
  def read(self, item_id: str) -> ItemT:
51
50
  try:
52
51
  raw = self.db.execute(self.table.select(item_id)).fetch_one()
53
52
  except OperationalError as e:
54
53
  if "Conversion failed" in str(e):
55
- raise DoesNotExistError(item_id)
56
- else:
57
- raise e
54
+ raise DoesNotExistError(item_id) from e
55
+ raise e
58
56
 
59
57
  if not raw:
60
58
  raise DoesNotExistError(item_id)
@@ -273,7 +271,7 @@ class DefaultSqlTable(SqlTable[ItemT]):
273
271
  [f"%({key.name})s" for key in self.fields if key.include_in_insert]
274
272
  )
275
273
  try:
276
- self.fields.id
274
+ _ = self.fields.id
277
275
  output = ", ".join(
278
276
  ["[" + field.name + "] AS " + field.name for field in self.fields]
279
277
  )
@@ -368,12 +366,11 @@ class DefaultSqlTable(SqlTable[ItemT]):
368
366
  def exists(self, duplicate: ItemT) -> ExistsError:
369
367
  raw = self.formatter.dump(duplicate)
370
368
  return ExistsError(duplicate).with_duplicate(
371
- lambda i: f"{self.fields.id}<{raw[self.fields.id]}>"
369
+ lambda _: f"{self.fields.id}<{raw[self.fields.id]}>"
372
370
  )
373
371
 
374
372
  @property
375
373
  def _user_check(self) -> str:
376
374
  if self.username is not None:
377
375
  return f"EXECUTE AS USER = '{self.username}'"
378
- else:
379
- return ""
376
+ return ""
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Callable, Iterator
3
4
  from dataclasses import dataclass, field
4
- from typing import Callable, Generic, Iterator, TypeVar
5
+ from typing import Generic, TypeVar
5
6
 
6
7
  from apexdevkit.error import DoesNotExistError
7
8
  from apexdevkit.formatter import Formatter
@@ -74,23 +75,35 @@ class MultipleRepositoryBuilder(Generic[ItemT]):
74
75
  def with_repository(
75
76
  self,
76
77
  repository: Repository[ItemT],
77
- condition: Callable[[ItemT], bool] = lambda item: True,
78
- formatter: Formatter[ItemT, ItemT] = NoFormatter[ItemT](),
78
+ condition: Callable[[ItemT], bool] = lambda _: True,
79
+ formatter: Formatter[ItemT, ItemT] | None = None,
79
80
  id_prefix: str = "",
80
81
  ) -> MultipleRepositoryBuilder[ItemT]:
81
82
  return MultipleRepositoryBuilder[ItemT](
82
83
  self.repositories
83
- + [_InnerRepository(repository, condition, formatter, id_prefix)]
84
+ + [
85
+ _InnerRepository(
86
+ repository,
87
+ condition,
88
+ formatter or NoFormatter[ItemT](),
89
+ id_prefix,
90
+ )
91
+ ]
84
92
  )
85
93
 
86
94
  def and_repository(
87
95
  self,
88
96
  repository: Repository[ItemT],
89
- condition: Callable[[ItemT], bool] = lambda item: True,
90
- formatter: Formatter[ItemT, ItemT] = NoFormatter[ItemT](),
97
+ condition: Callable[[ItemT], bool] = lambda _: True,
98
+ formatter: Formatter[ItemT, ItemT] | None = None,
91
99
  id_prefix: str = "",
92
100
  ) -> MultipleRepositoryBuilder[ItemT]:
93
- return self.with_repository(repository, condition, formatter, id_prefix)
101
+ return self.with_repository(
102
+ repository,
103
+ condition,
104
+ formatter or NoFormatter[ItemT](),
105
+ id_prefix,
106
+ )
94
107
 
95
108
  def build(self) -> MultipleRepository[ItemT]:
96
109
  return MultipleRepository[ItemT](self.repositories)
@@ -99,7 +112,7 @@ class MultipleRepositoryBuilder(Generic[ItemT]):
99
112
  @dataclass(frozen=True)
100
113
  class _InnerRepository(Generic[ItemT]):
101
114
  inner: Repository[ItemT]
102
- condition: Callable[[ItemT], bool] = lambda item: True
115
+ condition: Callable[[ItemT], bool] = lambda _: True
103
116
  formatter: Formatter[ItemT, ItemT] = field(
104
117
  default_factory=lambda: NoFormatter[ItemT]()
105
118
  )
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Iterator, Mapping
3
4
  from dataclasses import dataclass, field
4
- from typing import Any, Iterator, Mapping
5
+ from typing import Any
5
6
 
6
7
 
7
8
  @dataclass(frozen=True)
@@ -144,8 +145,8 @@ class SqlFieldManager:
144
145
  ]
145
146
  if len(ordering) > 0:
146
147
  return "ORDER BY " + ", ".join(order_clauses)
147
- else:
148
- return ""
148
+
149
+ return ""
149
150
 
150
151
  def __iter__(self) -> Iterator[_SqlField]:
151
152
  yield from self.fields
@@ -162,8 +163,8 @@ class SqlFieldManager:
162
163
  ]
163
164
  if len(statements) > 0:
164
165
  return "WHERE " + " AND ".join(statements)
165
- else:
166
- return ""
166
+
167
+ return ""
167
168
 
168
169
  def with_fixed(self, raw: Mapping[str, Any]) -> dict[str, Any]:
169
170
  data = dict(raw)
@@ -184,14 +185,13 @@ class SqlFieldManager:
184
185
  if result is not None:
185
186
  if result.parent_value is None:
186
187
  return self.key_formatter.replace("x", result.name) + " IS NULL"
187
- else:
188
- return (
189
- self.key_formatter.replace("x", result.name)
190
- + " = "
191
- + self.value_formatter.replace("x", result.name)
192
- )
193
- else:
194
- return ""
188
+ return (
189
+ self.key_formatter.replace("x", result.name)
190
+ + " = "
191
+ + self.value_formatter.replace("x", result.name)
192
+ )
193
+
194
+ return ""
195
195
 
196
196
  def _id_filter(self, include_id: bool, read_id: bool) -> str:
197
197
  return (
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Iterable, Iterator, Mapping
3
4
  from dataclasses import dataclass
4
5
  from sqlite3 import IntegrityError
5
- from typing import Any, Generic, Iterable, Iterator, Mapping
6
+ from typing import Any, Generic
6
7
 
7
8
  from apexdevkit.error import DoesNotExistError, ExistsError
8
9
  from apexdevkit.formatter import Formatter
@@ -28,8 +29,8 @@ class SqliteRepository(RepositoryBase[ItemT]):
28
29
 
29
30
  try:
30
31
  return int(raw["n_items"])
31
- except KeyError:
32
- raise UnknownError(raw)
32
+ except KeyError as e:
33
+ raise UnknownError(raw) from e
33
34
 
34
35
  def create(self, item: ItemT) -> ItemT:
35
36
  try:
@@ -60,7 +61,7 @@ class SqliteRepository(RepositoryBase[ItemT]):
60
61
 
61
62
 
62
63
  class SqlTable(Generic[ItemT]): # pragma: no cover
63
- def bind(self, **kwargs: Any) -> SqlTable[ItemT]:
64
+ def bind(self, **_: Any) -> SqlTable[ItemT]:
64
65
  return self
65
66
 
66
67
  def count_all(self) -> DatabaseCommand:
@@ -91,7 +92,7 @@ class SqlTable(Generic[ItemT]): # pragma: no cover
91
92
  raise NotImplementedError
92
93
 
93
94
  def duplicate(self, item: ItemT) -> ExistsError:
94
- return ExistsError(item).with_duplicate(lambda i: "Unknown")
95
+ return ExistsError(item).with_duplicate(lambda _: "Unknown")
95
96
 
96
97
 
97
98
  @dataclass
@@ -183,7 +184,7 @@ class _DefaultSqlTable(SqlTable[ItemT]):
183
184
 
184
185
  return DatabaseCommand(f"""
185
186
  SELECT
186
- {columns}
187
+ {columns}
187
188
  FROM {self.table_name.upper()}
188
189
  {self.fields.where_statement(include_id=True)};
189
190
  """).with_data(self.fields.with_fixed({self.fields.id: item_id}))
@@ -198,7 +199,7 @@ class _DefaultSqlTable(SqlTable[ItemT]):
198
199
 
199
200
  return DatabaseCommand(f"""
200
201
  SELECT
201
- {columns}
202
+ {columns}
202
203
  FROM {self.table_name.upper()}
203
204
  WHERE {duplicates};
204
205
  """).with_data({key: raw[key] for key in raw if key in self.fields.composite})
@@ -250,7 +251,7 @@ class _DefaultSqlTable(SqlTable[ItemT]):
250
251
  def duplicate(self, item: ItemT) -> ExistsError:
251
252
  raw = self.formatter.dump(item)
252
253
  return ExistsError(item).with_duplicate(
253
- lambda i: ",".join(
254
+ lambda _: ",".join(
254
255
  [f"{key}<{raw[key]}>" for key in raw if key in self.fields.composite]
255
256
  )
256
257
  )
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging.config
4
+ from collections.abc import Callable
4
5
  from dataclasses import dataclass, field
5
- from typing import Any, Callable
6
+ from typing import Any
6
7
 
7
8
  import sentry_sdk
8
9
  import uvicorn
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Iterable, Iterator
3
4
  from dataclasses import dataclass
4
- from typing import Generic, Iterable, Iterator, Protocol, TypeVar
5
+ from typing import Generic, Protocol, TypeVar
5
6
 
6
7
  ItemT = TypeVar("ItemT")
7
8
 
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- from contextlib import nullcontext
3
+ from contextlib import AbstractContextManager, nullcontext
4
4
  from dataclasses import dataclass, field
5
- from typing import Any, ContextManager, Self
5
+ from typing import Any, Self
6
6
 
7
7
  from apexdevkit.repository import DatabaseCommand
8
8
 
@@ -27,7 +27,7 @@ class FakeConnector:
27
27
  def fetchall(self) -> list[dict[str, Any]]:
28
28
  return self.results.pop() # type: ignore
29
29
 
30
- def connect(self) -> ContextManager[Self]:
30
+ def connect(self) -> AbstractContextManager[Self]:
31
31
  return nullcontext(self)
32
32
 
33
33
  def cursor(self) -> Self:
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import random
4
4
  from dataclasses import dataclass, field
5
5
  from functools import cached_property
6
- from typing import Any, Generic, Type, TypeVar
6
+ from typing import Any, Generic, TypeVar
7
7
 
8
8
  from faker import Faker
9
9
 
@@ -70,7 +70,7 @@ class Fake:
70
70
 
71
71
  @dataclass(frozen=True)
72
72
  class FakeResource(Generic[ItemT]):
73
- item_type: Type[ItemT] = field()
73
+ item_type: type[ItemT] = field()
74
74
  fake: Fake = field(default_factory=Fake)
75
75
 
76
76
  @cached_property
@@ -89,7 +89,7 @@ class FakeResource(Generic[ItemT]):
89
89
 
90
90
  @dataclass(frozen=True)
91
91
  class FakeValue(FakeResource[Value]):
92
- item_type: Type[Value] = field(default=Value)
92
+ item_type: type[Value] = field(default=Value)
93
93
 
94
94
  @cached_property
95
95
  def _raw(self) -> dict[str, Any]:
@@ -101,7 +101,7 @@ class FakeValue(FakeResource[Value]):
101
101
 
102
102
  @dataclass(frozen=True)
103
103
  class FakeNumericValue(FakeResource[NumericValue]):
104
- item_type: Type[NumericValue] = field(default=NumericValue)
104
+ item_type: type[NumericValue] = field(default=NumericValue)
105
105
 
106
106
  @cached_property
107
107
  def _raw(self) -> dict[str, Any]:
@@ -113,7 +113,7 @@ class FakeNumericValue(FakeResource[NumericValue]):
113
113
 
114
114
  @dataclass(frozen=True)
115
115
  class FakeStringValue(FakeResource[StringValue]):
116
- item_type: Type[StringValue] = field(default=StringValue)
116
+ item_type: type[StringValue] = field(default=StringValue)
117
117
 
118
118
  @cached_property
119
119
  def _raw(self) -> dict[str, Any]:
@@ -124,7 +124,7 @@ class FakeStringValue(FakeResource[StringValue]):
124
124
 
125
125
  @dataclass(frozen=True)
126
126
  class FakeDateValue(FakeResource[DateValue]):
127
- item_type: Type[DateValue] = field(default=DateValue)
127
+ item_type: type[DateValue] = field(default=DateValue)
128
128
 
129
129
  @cached_property
130
130
  def _raw(self) -> dict[str, Any]:
@@ -134,7 +134,7 @@ class FakeDateValue(FakeResource[DateValue]):
134
134
  @dataclass(frozen=True)
135
135
  class FakeLeaf(FakeResource[Leaf]):
136
136
  values: list[NumericValue | StringValue | DateValue] = field(default_factory=list)
137
- item_type: Type[Leaf] = field(default=Leaf)
137
+ item_type: type[Leaf] = field(default=Leaf)
138
138
 
139
139
  @cached_property
140
140
  def _raw(self) -> dict[str, Any]:
@@ -147,7 +147,7 @@ class FakeLeaf(FakeResource[Leaf]):
147
147
  @dataclass(frozen=True)
148
148
  class FakeOperator(FakeResource[Operator]):
149
149
  operands: list[Operator | Leaf] = field(default_factory=list)
150
- item_type: Type[Operator] = field(default=Operator)
150
+ item_type: type[Operator] = field(default=Operator)
151
151
 
152
152
  @cached_property
153
153
  def _raw(self) -> dict[str, Any]:
@@ -160,7 +160,7 @@ class FakeOperator(FakeResource[Operator]):
160
160
  @dataclass(frozen=True)
161
161
  class FakeSort(FakeResource[Sort]):
162
162
  is_descending: bool | None = None
163
- item_type: Type[Sort] = field(default=Sort)
163
+ item_type: type[Sort] = field(default=Sort)
164
164
 
165
165
  @cached_property
166
166
  def _raw(self) -> dict[str, Any]:
@@ -174,7 +174,7 @@ class FakeSort(FakeResource[Sort]):
174
174
 
175
175
  @dataclass(frozen=True)
176
176
  class FakePage(FakeResource[Page]):
177
- item_type: Type[Page] = field(default=Page)
177
+ item_type: type[Page] = field(default=Page)
178
178
 
179
179
  @cached_property
180
180
  def _raw(self) -> dict[str, Any]:
@@ -188,7 +188,7 @@ class FakePage(FakeResource[Page]):
188
188
  @dataclass(frozen=True)
189
189
  class FakeFilter(FakeResource[Filter]):
190
190
  args: list[NumericValue | StringValue] = field(default_factory=list)
191
- item_type: Type[Filter] = field(default=Filter)
191
+ item_type: type[Filter] = field(default=Filter)
192
192
 
193
193
  @cached_property
194
194
  def _raw(self) -> dict[str, Any]:
@@ -203,7 +203,7 @@ class FakeQueryOptions(FakeResource[QueryOptions]):
203
203
  condition: Operator | None = None
204
204
  ordering: list[Sort] = field(default_factory=list)
205
205
  paging: Page | None = None
206
- item_type: Type[QueryOptions] = field(default=QueryOptions)
206
+ item_type: type[QueryOptions] = field(default=QueryOptions)
207
207
 
208
208
  @cached_property
209
209
  def _raw(self) -> dict[str, Any]:
@@ -217,7 +217,7 @@ class FakeQueryOptions(FakeResource[QueryOptions]):
217
217
 
218
218
  @dataclass(frozen=True)
219
219
  class FakeAggregationOption(FakeResource[AggregationOption]):
220
- item_type: Type[AggregationOption] = field(default=AggregationOption)
220
+ item_type: type[AggregationOption] = field(default=AggregationOption)
221
221
 
222
222
  @cached_property
223
223
  def _raw(self) -> dict[str, Any]:
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Iterable
3
4
  from dataclasses import dataclass
4
5
  from functools import cached_property
5
- from typing import Any, Iterable, Self
6
+ from typing import Any, Self
6
7
 
7
8
  from apexdevkit.fastapi.name import RestfulName
8
9
  from apexdevkit.fastapi.request import HttpRequest
@@ -1,16 +1,19 @@
1
- [tool.poetry]
1
+ [project]
2
2
  name = "apexdevkit"
3
- version = "1.22.2"
3
+ version = "1.23.2"
4
4
  description = "Apex Development Tools for python."
5
- authors = ["Apex Dev <dev@apex.ge>"]
6
5
  readme = "README.md"
6
+ authors = [
7
+ { name = "Apex Dev", email = "dev@apex.ge" }
8
+ ]
9
+ dynamic = ["dependencies"]
10
+ requires-python = ">=3.11"
7
11
 
8
12
  [tool.poetry.dependencies]
9
- python = "^3.11"
10
13
  httpx = "*"
11
14
  fastapi = "*"
12
15
  uvicorn = "*"
13
- sentry-sdk = {extras = ["fastapi"], version = "*"}
16
+ sentry-sdk = { extras = ["fastapi"], version = "*" }
14
17
  python-dotenv = "*"
15
18
  pymssql = "2.3.2"
16
19
 
@@ -22,14 +25,12 @@ pytest-cov = "*"
22
25
  pytest-recording = "*"
23
26
  coverage = "*"
24
27
  faker = "*"
25
- mongomock = "*"
26
28
 
27
29
  [tool.poetry.group.lint.dependencies]
28
30
  mypy = "*"
29
31
  ruff = "*"
30
32
 
31
33
  [tool.mypy]
32
- python_version = "3.11"
33
34
  ignore_missing_imports = true
34
35
  strict = true
35
36
  exclude = [
@@ -38,7 +39,6 @@ exclude = [
38
39
  ]
39
40
 
40
41
  [tool.ruff]
41
- target-version = "py311"
42
42
  line-length = 88
43
43
 
44
44
  exclude = [
@@ -48,10 +48,29 @@ exclude = [
48
48
  "venv",
49
49
  ]
50
50
 
51
- lint.select = ["E", "F", "I"]
52
- lint.ignore = []
53
- lint.fixable = ["A", "B", "C", "D", "E", "F", "I"]
54
- lint.unfixable = []
51
+ [tool.ruff.lint]
52
+ select = [
53
+ "A", # flake8-builtins
54
+ "ARG", # flake8-unused-arguments
55
+ "B", # flake8-bugbear
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
62
+ "E", # pycodestyle errors
63
+ "W", # pycodestyle warnings
64
+ "F", # pyflakes
65
+ "I", # isort
66
+ "N", # pep8-naming
67
+ "UP", # pyupgrade
68
+ ]
69
+
70
+ [tool.ruff.lint.per-file-ignores]
71
+ "apexdevkit/fastapi/resource.py" = ["N803"]
72
+ "apexdevkit/fastapi/dependable.py" = ["N806"]
73
+
55
74
 
56
75
  [tool.ruff.lint.mccabe]
57
76
  max-complexity = 10
File without changes
File without changes