apexdevkit 1.18.5__tar.gz → 1.18.6__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-1.18.5 → apexdevkit-1.18.6}/PKG-INFO +1 -1
  2. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/query/generator.py +54 -33
  3. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/pyproject.toml +3 -4
  4. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/LICENSE +0 -0
  5. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/README.md +0 -0
  6. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/__init__.py +0 -0
  7. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/annotation/__init__.py +0 -0
  8. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/annotation/deprecate.py +0 -0
  9. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/environment.py +0 -0
  10. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/error.py +0 -0
  11. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fastapi/__init__.py +0 -0
  12. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fastapi/builder.py +0 -0
  13. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fastapi/dependable.py +0 -0
  14. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fastapi/docs.py +0 -0
  15. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fastapi/name.py +0 -0
  16. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fastapi/request.py +0 -0
  17. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fastapi/resource.py +0 -0
  18. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fastapi/response.py +0 -0
  19. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fastapi/router.py +0 -0
  20. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fastapi/schema.py +0 -0
  21. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fastapi/service.py +0 -0
  22. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/fluent.py +0 -0
  23. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/formatter.py +0 -0
  24. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/http/__init__.py +0 -0
  25. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/http/fake.py +0 -0
  26. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/http/fluent.py +0 -0
  27. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/http/httpx.py +0 -0
  28. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/http/json.py +0 -0
  29. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/http/url.py +0 -0
  30. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/key_fn.py +0 -0
  31. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/py.typed +0 -0
  32. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/query/__init__.py +0 -0
  33. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/query/query.py +0 -0
  34. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/repository/__init__.py +0 -0
  35. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/repository/base.py +0 -0
  36. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/repository/connector.py +0 -0
  37. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/repository/database.py +0 -0
  38. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/repository/decorator.py +0 -0
  39. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/repository/in_memory.py +0 -0
  40. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/repository/interface.py +0 -0
  41. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/repository/mongo.py +0 -0
  42. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/repository/mssql.py +0 -0
  43. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/repository/sql.py +0 -0
  44. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/repository/sqlite.py +0 -0
  45. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/server.py +0 -0
  46. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/synchronization.py +0 -0
  47. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/testing/__init__.py +0 -0
  48. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/testing/database.py +0 -0
  49. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/testing/fake.py +0 -0
  50. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/testing/rest.py +0 -0
  51. {apexdevkit-1.18.5 → apexdevkit-1.18.6}/apexdevkit/value.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apexdevkit
3
- Version: 1.18.5
3
+ Version: 1.18.6
4
4
  Summary: Apex Development Tools for python.
5
5
  Author: Apex Dev
6
6
  Author-email: dev@apex.ge
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from collections import defaultdict
4
4
  from dataclasses import dataclass, field
5
+ from functools import cached_property
5
6
  from typing import Any, ClassVar, Generic, Iterable, Protocol, TypeVar
6
7
 
7
8
  from apexdevkit.error import ForbiddenError
@@ -150,6 +151,10 @@ class MsSqlQueryBuilder:
150
151
  username: str = field(init=False)
151
152
  translations: dict[str, str] = field(init=False)
152
153
 
154
+ @cached_property
155
+ def _fields(self) -> list[MsSqlField]:
156
+ return [MsSqlField(name, alias) for alias, name in self.translations.items()]
157
+
153
158
  def with_source(self, value: str) -> MsSqlQueryBuilder:
154
159
  self.source = value
155
160
 
@@ -176,10 +181,10 @@ class MsSqlQueryBuilder:
176
181
  def filter(self, options: QueryOptions) -> DatabaseCommand:
177
182
  return MsSqlQuery(
178
183
  user=MsSqlUserGenerator(self.username),
179
- selection=MsSqlSelectionGenerator(self.translations),
184
+ selection=MsSqlSelectionGenerator(self._fields),
180
185
  filter=MsSqlSourceGenerator(self.source, options.filter),
181
186
  condition=MsSqlConditionGenerator(options.condition, self.translations),
182
- ordering=MsSqlOrderGenerator(options.ordering, self.translations),
187
+ ordering=MsSqlOrderGenerator(options.ordering, self._fields),
183
188
  paging=MsSqlPagingGenerator(options.paging),
184
189
  ).generate()
185
190
 
@@ -192,17 +197,35 @@ class MsSqlUserGenerator:
192
197
  return f"EXECUTE AS USER = '{self.username}'"
193
198
 
194
199
 
200
+ @dataclass
201
+ class MsSqlField:
202
+ name: str
203
+
204
+ alias: str = ""
205
+
206
+ def as_select_part(self) -> str:
207
+ result = f"[{self.name}]"
208
+
209
+ if self.alias:
210
+ result += f" AS [{self.alias}]"
211
+
212
+ return result
213
+
214
+ def as_order_part(self, is_descending: bool = False) -> str:
215
+ result = self.alias or self.name
216
+
217
+ if is_descending:
218
+ result += " DESC"
219
+
220
+ return result
221
+
222
+
195
223
  @dataclass
196
224
  class MsSqlSelectionGenerator:
197
- translations: dict[str, str]
225
+ fields: list[MsSqlField] = field(default_factory=list)
198
226
 
199
227
  def generate(self) -> str:
200
- fields = ", ".join(
201
- [
202
- f"[{self.translations[key]}] AS [{key}]"
203
- for key in self.translations.keys()
204
- ]
205
- )
228
+ fields = ", ".join([f.as_select_part() for f in self.fields])
206
229
 
207
230
  return f"SELECT {fields}"
208
231
 
@@ -242,18 +265,17 @@ class MsSqlSourceGenerator:
242
265
  return f"FROM {self.source}{self._argument_list()}"
243
266
 
244
267
  def _argument_list(self) -> str:
245
- if self.filter is not None:
246
- return (
247
- "("
248
- + ",".join(
249
- arg.as_arg() if arg is not None else "null"
250
- for arg in self.filter.args
251
- )
252
- + ")"
253
- )
254
- else:
268
+ if self.filter is None:
255
269
  return ""
256
270
 
271
+ return (
272
+ "("
273
+ + ",".join(
274
+ arg.as_arg() if arg is not None else "null" for arg in self.filter.args
275
+ )
276
+ + ")"
277
+ )
278
+
257
279
 
258
280
  @dataclass
259
281
  class MsSqlConditionGenerator:
@@ -304,27 +326,26 @@ class MsSqlConditionGenerator:
304
326
  @dataclass
305
327
  class MsSqlOrderGenerator:
306
328
  ordering: list[Sort]
307
- translations: dict[str, str]
329
+
330
+ fields: list[MsSqlField] = field(default_factory=list)
308
331
 
309
332
  def generate(self) -> str:
310
333
  if not self.ordering:
311
334
  return ""
312
- self._validate()
313
335
 
314
- order_clause = ", ".join(
315
- f"{self.translations[item.name]} DESC"
316
- if item.is_descending
317
- else self.translations[item.name]
318
- for item in self.ordering
319
- )
336
+ clause = ", ".join(self.generate_one(item) for item in self.ordering)
320
337
 
321
- return f"ORDER BY {order_clause}"
338
+ return f"ORDER BY {clause}"
322
339
 
323
- def _validate(self) -> None:
324
- if self.translations.keys():
325
- for order in self.ordering:
326
- if order.name not in self.translations.keys():
327
- raise ForbiddenError(message=f"Invalid field name: {order.name}")
340
+ def generate_one(self, item: Sort) -> str:
341
+ return self.field_for(item.name).as_order_part(item.is_descending)
342
+
343
+ def field_for(self, name: str) -> MsSqlField:
344
+ for f in self.fields:
345
+ if f.name == name:
346
+ return f
347
+
348
+ raise ForbiddenError(message=f"Invalid field name: {name}")
328
349
 
329
350
 
330
351
  @dataclass
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "apexdevkit"
3
- version = "1.18.5"
3
+ version = "1.18.6"
4
4
  description = "Apex Development Tools for python."
5
5
  authors = ["Apex Dev <dev@apex.ge>"]
6
6
  readme = "README.md"
@@ -16,7 +16,9 @@ python-dotenv = "*"
16
16
  pymssql = "^2.3.1"
17
17
 
18
18
  [tool.poetry.group.dev.dependencies]
19
+ approvaltests = "*"
19
20
  pytest = "*"
21
+ pytest-approvaltests = "*"
20
22
  pytest-cov = "*"
21
23
  pytest-recording = "*"
22
24
  coverage = "*"
@@ -61,9 +63,6 @@ source = [
61
63
  "apexdevkit",
62
64
  "tests",
63
65
  ]
64
- omit = [
65
- "apexdevkit/server.py",
66
- ]
67
66
 
68
67
  [tool.coverage.report]
69
68
  skip_empty = true
File without changes
File without changes