ormlambda 3.35.2__py3-none-any.whl → 4.0.0__py3-none-any.whl

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 (130) hide show
  1. ormlambda/__init__.py +79 -51
  2. ormlambda/caster/caster.py +6 -1
  3. ormlambda/common/abstract_classes/__init__.py +0 -2
  4. ormlambda/common/enums/__init__.py +1 -0
  5. ormlambda/common/enums/order_type.py +9 -0
  6. ormlambda/common/errors/__init__.py +13 -3
  7. ormlambda/common/global_checker.py +86 -8
  8. ormlambda/common/interfaces/IQueryCommand.py +2 -2
  9. ormlambda/common/interfaces/__init__.py +0 -2
  10. ormlambda/dialects/__init__.py +75 -3
  11. ormlambda/dialects/default/base.py +1 -1
  12. ormlambda/dialects/mysql/__init__.py +35 -78
  13. ormlambda/dialects/mysql/base.py +226 -40
  14. ormlambda/dialects/mysql/clauses/ST_AsText.py +26 -0
  15. ormlambda/dialects/mysql/clauses/ST_Contains.py +30 -0
  16. ormlambda/dialects/mysql/clauses/__init__.py +1 -0
  17. ormlambda/dialects/mysql/repository/__init__.py +1 -0
  18. ormlambda/{databases/my_sql → dialects/mysql/repository}/repository.py +0 -5
  19. ormlambda/dialects/mysql/types.py +6 -0
  20. ormlambda/engine/base.py +26 -4
  21. ormlambda/errors.py +9 -0
  22. ormlambda/model/base_model.py +3 -10
  23. ormlambda/repository/base_repository.py +1 -1
  24. ormlambda/repository/interfaces/IRepositoryBase.py +0 -7
  25. ormlambda/repository/response.py +12 -7
  26. ormlambda/sql/__init__.py +12 -3
  27. ormlambda/sql/clause_info/__init__.py +0 -2
  28. ormlambda/sql/clause_info/clause_info.py +94 -76
  29. ormlambda/sql/clause_info/interface/IAggregate.py +14 -4
  30. ormlambda/sql/clause_info/interface/IClauseInfo.py +6 -11
  31. ormlambda/sql/clauses/alias.py +6 -37
  32. ormlambda/sql/clauses/count.py +21 -36
  33. ormlambda/sql/clauses/group_by.py +13 -19
  34. ormlambda/sql/clauses/having.py +2 -6
  35. ormlambda/sql/clauses/insert.py +3 -3
  36. ormlambda/sql/clauses/interfaces/__init__.py +0 -1
  37. ormlambda/sql/clauses/join/join_context.py +5 -12
  38. ormlambda/sql/clauses/joins.py +34 -52
  39. ormlambda/sql/clauses/limit.py +1 -2
  40. ormlambda/sql/clauses/offset.py +1 -2
  41. ormlambda/sql/clauses/order.py +17 -21
  42. ormlambda/sql/clauses/select.py +56 -28
  43. ormlambda/sql/clauses/update.py +13 -10
  44. ormlambda/sql/clauses/where.py +20 -39
  45. ormlambda/sql/column/__init__.py +1 -0
  46. ormlambda/sql/column/column.py +19 -12
  47. ormlambda/sql/column/column_proxy.py +117 -0
  48. ormlambda/sql/column_table_proxy.py +23 -0
  49. ormlambda/sql/comparer.py +31 -65
  50. ormlambda/sql/compiler.py +248 -58
  51. ormlambda/sql/context/__init__.py +304 -0
  52. ormlambda/sql/ddl.py +19 -5
  53. ormlambda/sql/elements.py +3 -0
  54. ormlambda/sql/foreign_key.py +42 -64
  55. ormlambda/sql/functions/__init__.py +0 -1
  56. ormlambda/sql/functions/concat.py +35 -38
  57. ormlambda/sql/functions/max.py +12 -36
  58. ormlambda/sql/functions/min.py +13 -28
  59. ormlambda/sql/functions/sum.py +17 -33
  60. ormlambda/sql/sqltypes.py +2 -0
  61. ormlambda/sql/table/__init__.py +1 -0
  62. ormlambda/sql/table/table.py +32 -49
  63. ormlambda/sql/table/table_proxy.py +88 -0
  64. ormlambda/sql/type_api.py +4 -1
  65. ormlambda/sql/types.py +15 -12
  66. ormlambda/statements/__init__.py +0 -2
  67. ormlambda/statements/base_statement.py +51 -84
  68. ormlambda/statements/interfaces/IStatements.py +77 -123
  69. ormlambda/statements/interfaces/__init__.py +1 -1
  70. ormlambda/statements/query_builder.py +296 -128
  71. ormlambda/statements/statements.py +120 -110
  72. ormlambda/statements/types.py +5 -25
  73. ormlambda/util/__init__.py +7 -86
  74. ormlambda/util/langhelpers.py +102 -0
  75. ormlambda/util/module_tree/dynamic_module.py +1 -1
  76. ormlambda/util/preloaded.py +80 -0
  77. ormlambda/util/typing.py +12 -3
  78. {ormlambda-3.35.2.dist-info → ormlambda-4.0.0.dist-info}/METADATA +29 -31
  79. ormlambda-4.0.0.dist-info/RECORD +139 -0
  80. ormlambda/common/abstract_classes/clause_info_converter.py +0 -65
  81. ormlambda/common/abstract_classes/decomposition_query.py +0 -141
  82. ormlambda/common/abstract_classes/query_base.py +0 -15
  83. ormlambda/common/interfaces/ICustomAlias.py +0 -7
  84. ormlambda/common/interfaces/IDecompositionQuery.py +0 -33
  85. ormlambda/databases/__init__.py +0 -4
  86. ormlambda/databases/my_sql/__init__.py +0 -3
  87. ormlambda/databases/my_sql/clauses/ST_AsText.py +0 -37
  88. ormlambda/databases/my_sql/clauses/ST_Contains.py +0 -36
  89. ormlambda/databases/my_sql/clauses/__init__.py +0 -14
  90. ormlambda/databases/my_sql/clauses/count.py +0 -33
  91. ormlambda/databases/my_sql/clauses/delete.py +0 -9
  92. ormlambda/databases/my_sql/clauses/drop_table.py +0 -26
  93. ormlambda/databases/my_sql/clauses/group_by.py +0 -17
  94. ormlambda/databases/my_sql/clauses/having.py +0 -12
  95. ormlambda/databases/my_sql/clauses/insert.py +0 -9
  96. ormlambda/databases/my_sql/clauses/joins.py +0 -14
  97. ormlambda/databases/my_sql/clauses/limit.py +0 -6
  98. ormlambda/databases/my_sql/clauses/offset.py +0 -6
  99. ormlambda/databases/my_sql/clauses/order.py +0 -8
  100. ormlambda/databases/my_sql/clauses/update.py +0 -8
  101. ormlambda/databases/my_sql/clauses/upsert.py +0 -9
  102. ormlambda/databases/my_sql/clauses/where.py +0 -7
  103. ormlambda/dialects/interface/__init__.py +0 -1
  104. ormlambda/dialects/interface/dialect.py +0 -78
  105. ormlambda/sql/clause_info/aggregate_function_base.py +0 -96
  106. ormlambda/sql/clause_info/clause_info_context.py +0 -87
  107. ormlambda/sql/clauses/interfaces/ISelect.py +0 -17
  108. ormlambda/sql/clauses/new_join.py +0 -119
  109. ormlambda/util/load_module.py +0 -21
  110. ormlambda/util/plugin_loader.py +0 -32
  111. ormlambda-3.35.2.dist-info/RECORD +0 -159
  112. /ormlambda/{databases/my_sql → dialects/mysql}/caster/__init__.py +0 -0
  113. /ormlambda/{databases/my_sql → dialects/mysql}/caster/caster.py +0 -0
  114. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/__init__.py +0 -0
  115. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/boolean.py +0 -0
  116. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/bytes.py +0 -0
  117. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/date.py +0 -0
  118. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/datetime.py +0 -0
  119. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/decimal.py +0 -0
  120. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/float.py +0 -0
  121. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/int.py +0 -0
  122. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/iterable.py +0 -0
  123. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/json.py +0 -0
  124. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/none.py +0 -0
  125. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/point.py +0 -0
  126. /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/string.py +0 -0
  127. /ormlambda/{databases/my_sql → dialects/mysql/repository}/pool_types.py +0 -0
  128. {ormlambda-3.35.2.dist-info → ormlambda-4.0.0.dist-info}/AUTHORS +0 -0
  129. {ormlambda-3.35.2.dist-info → ormlambda-4.0.0.dist-info}/LICENSE +0 -0
  130. {ormlambda-3.35.2.dist-info → ormlambda-4.0.0.dist-info}/WHEEL +0 -0
ormlambda/__init__.py CHANGED
@@ -1,59 +1,87 @@
1
- import ormlambda.env # noqa: F401 Necesary to load all variables inside ormalambda.env
1
+ # COMMENT: Necesary to load all variables inside ormalambda.env
2
+ import ormlambda.env # noqa: F401
2
3
 
3
4
  # region enums
4
- from .common.enums import (
5
- JoinType as JoinType,
6
- ConditionType as ConditionType,
7
- )
5
+ from .common.enums import JoinType as JoinType
6
+ from .common.enums import ConditionType as ConditionType
7
+ from .common.enums import OrderType as OrderType
8
+
9
+
8
10
  # endregion
9
11
 
10
12
  # region sql
11
- from .sql import (
12
- Table as Table,
13
- Column as Column,
14
- ForeignKey as ForeignKey,
15
- )
13
+ from .sql import Column as Column
14
+ from .sql import ColumnProxy as ColumnProxy
15
+ from .sql import Table as Table
16
+ from .sql import ForeignKey as ForeignKey
17
+ from .sql import TableProxy as TableProxy
18
+
19
+
16
20
  # endregion
17
21
 
18
22
  from .repository import BaseRepository as BaseRepository
19
- from .statements import BaseStatement as BaseStatement
20
- from .statements.types import OrderType as OrderType
21
- from .model.base_model import (
22
- BaseModel as BaseModel,
23
- ORM as ORM,
24
- ) # COMMENT: to avoid relative import we need to import BaseModel after import Table,Column, ForeignKey, IRepositoryBase and Disassembler
25
-
26
- from .engine import create_engine, URL, make_url # noqa: F401
27
-
28
- from .sql.sqltypes import ( # noqa: F401
29
- JSON as JSON,
30
- UUID as UUID,
31
- NullType as NullType,
32
- INTEGER as INTEGER,
33
- INT as INT,
34
- SMALLINTEGER as SMALLINTEGER,
35
- BIGINTEGER as BIGINTEGER,
36
- NUMERIC as NUMERIC,
37
- FLOAT as FLOAT,
38
- REAL as REAL,
39
- DOUBLE as DOUBLE,
40
- DECIMAL as DECIMAL,
41
- STRING as STRING,
42
- TEXT as TEXT,
43
- UNICODE as UNICODE,
44
- UNICODETEXT as UNICODETEXT,
45
- CHAR as CHAR,
46
- NCHAR as NCHAR,
47
- BLOB as BLOB,
48
- VARCHAR as VARCHAR,
49
- NVARCHAR as NVARCHAR,
50
- DATE as DATE,
51
- TIME as TIME,
52
- DATETIME as DATETIME,
53
- TIMESTAMP as TIMESTAMP,
54
- BOOLEAN as BOOLEAN,
55
- LARGEBINARY as LARGEBINARY,
56
- VARBINARY as VARBINARY,
57
- ENUM as ENUM,
58
- POINT as POINT,
59
- )
23
+
24
+ from .model.base_model import BaseModel as BaseModel
25
+ from .model.base_model import ORM as ORM
26
+ # COMMENT: to avoid relative import we need to import BaseModel after import Table,Column, ForeignKey, IRepositoryBase and Disassembler
27
+
28
+ from .engine import create_engine as create_engine
29
+ from .engine import URL as URL
30
+ from .engine import make_url as make_url
31
+
32
+ from .sql.sqltypes import JSON as JSON
33
+ from .sql.sqltypes import UUID as UUID
34
+ from .sql.sqltypes import NullType as NullType
35
+ from .sql.sqltypes import INTEGER as INTEGER
36
+ from .sql.sqltypes import INT as INT
37
+ from .sql.sqltypes import SMALLINTEGER as SMALLINTEGER
38
+ from .sql.sqltypes import BIGINTEGER as BIGINTEGER
39
+ from .sql.sqltypes import NUMERIC as NUMERIC
40
+ from .sql.sqltypes import FLOAT as FLOAT
41
+ from .sql.sqltypes import REAL as REAL
42
+ from .sql.sqltypes import DOUBLE as DOUBLE
43
+ from .sql.sqltypes import DECIMAL as DECIMAL
44
+ from .sql.sqltypes import STRING as STRING
45
+ from .sql.sqltypes import TEXT as TEXT
46
+ from .sql.sqltypes import UNICODE as UNICODE
47
+ from .sql.sqltypes import UNICODETEXT as UNICODETEXT
48
+ from .sql.sqltypes import CHAR as CHAR
49
+ from .sql.sqltypes import NCHAR as NCHAR
50
+ from .sql.sqltypes import BLOB as BLOB
51
+ from .sql.sqltypes import VARCHAR as VARCHAR
52
+ from .sql.sqltypes import NVARCHAR as NVARCHAR
53
+ from .sql.sqltypes import DATE as DATE
54
+ from .sql.sqltypes import TIME as TIME
55
+ from .sql.sqltypes import DATETIME as DATETIME
56
+ from .sql.sqltypes import TIMESTAMP as TIMESTAMP
57
+ from .sql.sqltypes import BOOLEAN as BOOLEAN
58
+ from .sql.sqltypes import LARGEBINARY as LARGEBINARY
59
+ from .sql.sqltypes import VARBINARY as VARBINARY
60
+ from .sql.sqltypes import ENUM as ENUM
61
+ from .sql.sqltypes import POINT as POINT
62
+
63
+
64
+ from .sql.clauses import Alias as Alias
65
+ from .sql.clauses import Count as Count
66
+ from .sql.clauses import Delete as Delete
67
+ from .sql.clauses import GroupBy as GroupBy
68
+ from .sql.clauses import Insert as Insert
69
+ from .sql.clauses import JoinSelector as JoinSelector
70
+ from .sql.clauses import Limit as Limit
71
+ from .sql.clauses import Offset as Offset
72
+ from .sql.clauses import Order as Order
73
+ from .sql.clauses import Select as Select
74
+ from .sql.clauses import Where as Where
75
+ from .sql.clauses import Having as Having
76
+ from .sql.clauses import Update as Update
77
+ from .sql.clauses import Upsert as Upsert
78
+
79
+ from .sql.functions import Max as Max
80
+ from .sql.functions import Min as Min
81
+ from .sql.functions import Concat as Concat
82
+ from .sql.functions import Sum as Sum
83
+
84
+
85
+ from . import util as _util
86
+
87
+ _util.import_prefix("ormlambda")
@@ -62,4 +62,9 @@ class Caster(ICaster):
62
62
  column_type = type(value)
63
63
  else:
64
64
  column_type = type_value
65
- return cls.CASTER_SELECTOR()[column_type](value, column_type)
65
+
66
+ caster_class = cls.CASTER_SELECTOR().get(column_type, None)
67
+ if not caster_class:
68
+ raise ValueError(f"'{column_type}' type has not a Caster class created.")
69
+
70
+ return caster_class(value, column_type)
@@ -1,3 +1 @@
1
1
  from .non_query_base import NonQueryBase as NonQueryBase
2
- from .query_base import QueryBase as QueryBase
3
- from .decomposition_query import DecompositionQueryBase as DecompositionQueryBase
@@ -1,2 +1,3 @@
1
1
  from .join_type import JoinType # noqa: F401
2
2
  from .condition_types import ConditionType # noqa: F401
3
+ from .order_type import OrderType # noqa: F401
@@ -0,0 +1,9 @@
1
+ import enum
2
+
3
+
4
+ class OrderType(str, enum.Enum):
5
+ def __str__(self):
6
+ return super().__str__()
7
+
8
+ ASC = "ASC"
9
+ DESC = "DESC"
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
  import inspect
3
3
  import typing as tp
4
4
 
5
+ from ormlambda import util
5
6
 
6
7
  if tp.TYPE_CHECKING:
7
8
  from ormlambda.sql.clause_info import ClauseInfo
@@ -35,16 +36,25 @@ class AggregateFunctionError[T](Exception):
35
36
  agg_methods = self.__get_all_aggregate_method(self.clause)
36
37
  return f"You cannot use aggregation method like '{agg_methods}' to return model objects. Try specifying 'flavour' attribute as 'dict'."
37
38
 
39
+ @util.preload_module("ormlambda.sql.clause_info")
38
40
  def __get_all_aggregate_method(self, clauses: list[ClauseInfo]) -> str:
39
41
  """
40
- Get the class name of those classes that inherit from 'AggregateFunctionBase' class in order to create a better error message.
42
+ Get the class name of those classes that inherit from 'IAggregate' class in order to create a better error message.
41
43
  """
42
- from ormlambda.sql.clause_info import AggregateFunctionBase
43
44
 
45
+ IAggregate = util.preloaded.sql_clause_info.IAggregate
44
46
  res: set[str] = set()
45
47
  if not isinstance(clauses, tp.Iterable):
46
48
  return clauses.__class__.__name__
47
49
  for clause in clauses:
48
- if isinstance(clause, AggregateFunctionBase):
50
+ if isinstance(clause, IAggregate):
49
51
  res.add(clause.__class__.__name__)
50
52
  return ", ".join(res)
53
+
54
+
55
+ class NotCallableError(ValueError):
56
+ def __init__(self, *args):
57
+ super().__init__(*args)
58
+
59
+ def __str__(self)->str:
60
+ return f"You must provide a function or callable to proceed with the query creation. Passed '{self.args[0].__class__.__name__}' "
@@ -1,28 +1,106 @@
1
1
  from __future__ import annotations
2
2
  import re
3
- from typing import Any, TYPE_CHECKING
3
+ from typing import Any, TYPE_CHECKING, Iterable, Callable
4
4
 
5
5
  from ormlambda.common.errors import UnmatchedLambdaParameterError
6
+ from ormlambda.common.errors import NotCallableError
7
+ from ormlambda import util
6
8
 
7
9
  if TYPE_CHECKING:
8
- from ormlambda.sql import Table
10
+ from ormlambda.sql.types import SelectCol # FIXME [ ]: enhance the name
11
+ from ormlambda import TableProxy
12
+ from ormlambda.sql.column import ColumnProxy
9
13
 
10
14
 
11
- class GlobalChecker:
15
+ # type LambdaResponse[T] = TableProxy[T] | ColumnProxy[T] | Comparer
16
+ class GlobalChecker[T: TableProxy]:
17
+ FIRST_QUOTE = "`"
18
+ END_QUOTE = "`"
19
+
12
20
  @staticmethod
13
21
  def is_lambda_function(obj: Any) -> bool:
14
22
  return callable(obj) and not isinstance(obj, type)
15
23
 
24
+ @util.preload_module("ormlambda.sql")
16
25
  @classmethod
17
- def resolved_callback_object(cls, obj: Any, tables: tuple[Table, ...]):
18
- if not cls.is_lambda_function(obj):
19
- return obj
26
+ def resolved_callback_object(cls, table: T, lambda_func: Callable[[T], Any]) -> tuple[SelectCol, ...]:
27
+ TableProxy = util.preloaded.sql_table.TableProxy
20
28
 
21
29
  try:
22
- return obj(*tables)
30
+ table_proxy = TableProxy(table)
31
+
32
+ if not callable(lambda_func):
33
+ raise NotCallableError(lambda_func)
34
+
35
+ if isinstance(lambda_func, Iterable):
36
+ # We hit that condition when trying to pass column or function dynamically into select clause.
37
+
38
+ # max_fn = Max(lambda x: x.Col1)
39
+ # min_fn = Min(lambda x: x.Col1)
40
+ # sum_fn = Sum(lambda x: x.Col1)
41
+ # result = self.model.select(
42
+ # (
43
+ # max_fn,
44
+ # min_fn,
45
+ # sum_fn,
46
+ # ),
47
+ # flavour=dict,
48
+ # )
49
+
50
+ response = []
51
+
52
+ for item in lambda_func:
53
+ response.append(item)
54
+ return response
55
+
56
+ response = lambda_func(table_proxy)
57
+ result = []
58
+
59
+ if isinstance(response, str) or not isinstance(response, Iterable):
60
+ response = [response]
61
+
62
+ for item in response:
63
+ column = cls.parser_object(item, table)
64
+
65
+ result.extend(column)
66
+
67
+ return result
68
+
23
69
  except TypeError as err:
24
70
  cond1 = r"takes \d+ positional argument but \d+ were given"
25
71
  cond2 = r"missing \d+ required positional arguments:"
26
72
  if re.search(r"(" + f"{cond1}|{cond2}" + r")", err.args[0]):
27
- raise UnmatchedLambdaParameterError(len(tables), obj)
73
+ raise UnmatchedLambdaParameterError(len(table), lambda_func)
28
74
  raise err
75
+
76
+ @util.preload_module(
77
+ "ormlambda.sql.column",
78
+ "ormlambda.sql.table",
79
+ "ormlambda.sql.comparer",
80
+ "ormlambda.sql.column_table_proxy",
81
+ )
82
+ @staticmethod
83
+ def parser_object(item: Any, table: T) -> tuple[ColumnProxy, ...]:
84
+ ColumnProxy = util.preloaded.sql_column.ColumnProxy
85
+ Column = util.preloaded.sql_column.Column
86
+
87
+ TableProxy = util.preloaded.sql_table.TableProxy
88
+ Comparer = util.preloaded.sql_comparer.Comparer
89
+ FKChain = util.preloaded.sql_column_table_proxy.FKChain
90
+
91
+ if isinstance(item, TableProxy):
92
+ return item.get_columns()
93
+
94
+ if isinstance(item, str):
95
+ # If we got a string, probably means that it'll be an alias,
96
+ # so we'll want to avoid add string alias table to alias like `address`.count
97
+ new_col = Column(dtype=str, column_name=item)
98
+ new_col.table = table
99
+ return [ColumnProxy(new_col, path=FKChain(table, None))]
100
+ if isinstance(item, Comparer):
101
+ return [item]
102
+
103
+ if isinstance(item, ColumnProxy):
104
+ return [item]
105
+
106
+ return [item]
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from abc import abstractmethod, ABC
2
+ from abc import ABC
3
3
  from typing import TYPE_CHECKING
4
4
 
5
5
  if TYPE_CHECKING:
@@ -9,7 +9,7 @@ if TYPE_CHECKING:
9
9
  class IQuery(ABC):
10
10
  """Interface to queries that retrieve any element such as select, limit, offset, where, group by, etc..."""
11
11
 
12
- @abstractmethod
12
+ # @abstractmethod
13
13
  def query(self, dialect: Dialect, **kwargs) -> str: ...
14
14
 
15
15
  def __repr__(self) -> str:
@@ -1,5 +1,3 @@
1
- from .ICustomAlias import ICustomAlias as ICustomAlias
2
- from .IDecompositionQuery import IDecompositionQuery as IDecompositionQuery
3
1
  from .IJoinSelector import IJoinSelector as IJoinSelector
4
2
  from .INonQueryCommand import INonQueryCommand as INonQueryCommand
5
3
  from .IQueryCommand import IQuery as IQuery
@@ -1,13 +1,83 @@
1
1
  from __future__ import annotations
2
- from typing import Callable, Optional, Type, TYPE_CHECKING
2
+ from typing import Callable, Optional, Type, TYPE_CHECKING, ClassVar
3
+ import abc
3
4
  from ormlambda import util
4
5
  import importlib
5
6
 
7
+
6
8
  if TYPE_CHECKING:
7
- from .interface import Dialect
9
+ from ormlambda.caster.caster import Caster
10
+ from ormlambda.repository.interfaces.IRepositoryBase import DBAPIConnection
11
+ from ormlambda.sql.types import DDLCompiler, SQLCompiler, TypeCompiler
12
+ from ormlambda import BaseRepository
8
13
 
9
14
 
10
- __all__ = ("mysql", "sqlite")
15
+ class Dialect(abc.ABC):
16
+ """
17
+ Abstract base class for all database dialects.
18
+ """
19
+
20
+ dbapi: Optional[DBAPIConnection]
21
+ """A reference to the DBAPI module object itself.
22
+
23
+ Ormlambda dialects import DBAPI modules using the classmethod
24
+ :meth:`.Dialect.import_dbapi`. The rationale is so that any dialect
25
+ module can be imported and used to generate SQL statements without the
26
+ need for the actual DBAPI driver to be installed. Only when an
27
+ :class:`.Engine` is constructed using :func:`.create_engine` does the
28
+ DBAPI get imported; at that point, the creation process will assign
29
+ the DBAPI module to this attribute.
30
+
31
+ Dialects should therefore implement :meth:`.Dialect.import_dbapi`
32
+ which will import the necessary module and return it, and then refer
33
+ to ``self.dbapi`` in dialect code in order to refer to the DBAPI module
34
+ contents.
35
+
36
+ .. versionchanged:: The :attr:`.Dialect.dbapi` attribute is exclusively
37
+ used as the per-:class:`.Dialect`-instance reference to the DBAPI
38
+ module. The previous not-fully-documented ``.Dialect.dbapi()``
39
+ classmethod is deprecated and replaced by :meth:`.Dialect.import_dbapi`.
40
+
41
+ """
42
+
43
+ name: ClassVar[str]
44
+ """The name of the dialect, e.g. 'sqlite', 'postgresql', etc."""
45
+ driver: ClassVar[str]
46
+ """The driver used by the dialect, e.g. 'sqlite3', 'psycopg2', etc."""
47
+
48
+ ddl_compiler: ClassVar[Type[DDLCompiler]]
49
+ """The DDL compiler class used by the dialect."""
50
+
51
+ statement_compiler: ClassVar[Type[SQLCompiler]]
52
+ """The statement compiler class used by the dialect."""
53
+
54
+ type_compiler_cls: ClassVar[Type[TypeCompiler]]
55
+ """The type compiler class used by the dialect."""
56
+
57
+ type_compiler_instance: ClassVar[TypeCompiler]
58
+ """The instance of the type compiler class used by the dialect."""
59
+
60
+ repository_cls: ClassVar[Type[BaseRepository]]
61
+ """The repository class used by the dialect."""
62
+
63
+ caster: ClassVar[Type[Caster]]
64
+
65
+ @classmethod
66
+ def get_dialect_cls(cls) -> Type[Dialect]:
67
+ return cls
68
+
69
+ @classmethod
70
+ @abc.abstractmethod
71
+ def import_dbapi(cls) -> DBAPIConnection:
72
+ """
73
+ Import the DB API module for the dialect.
74
+ This method should be implemented by subclasses to import the
75
+ appropriate DB API module for the dialect.
76
+ """
77
+ ...
78
+
79
+ def __repr__(self):
80
+ return f"{Dialect.__name__}: {type(self).__name__}"
11
81
 
12
82
 
13
83
  def _auto_fn(name: str) -> Optional[Callable[[], Type[Dialect]]]:
@@ -37,3 +107,5 @@ def _auto_fn(name: str) -> Optional[Callable[[], Type[Dialect]]]:
37
107
 
38
108
 
39
109
  registry = util.PluginLoader("ormlambda.dialects", auto_fn=_auto_fn)
110
+
111
+ __all__ = ("mysql", "sqlite")
@@ -1,4 +1,4 @@
1
- from ormlambda.dialects.interface import Dialect
1
+ from ormlambda.dialects import Dialect
2
2
  from ormlambda.sql import compiler
3
3
  from typing import Optional, Any
4
4
  from types import ModuleType
@@ -1,84 +1,41 @@
1
- from . import base
2
- from . import mysqlconnector
1
+ from . import base as base
2
+ from . import mysqlconnector as mysqlconnector
3
3
 
4
- from .base import BIGINT
5
- from .base import BINARY
6
- from .base import BIT
7
- from .base import BLOB
8
- from .base import BOOLEAN
9
- from .base import CHAR
10
- from .base import DATE
11
- from .base import DATETIME
12
- from .base import DECIMAL
13
- from .base import DOUBLE
14
- from .base import FLOAT
15
- from .base import INTEGER
16
- from .base import LONGBLOB
17
- from .base import LONGTEXT
18
- from .base import MEDIUMBLOB
19
- from .base import MEDIUMINT
20
- from .base import MEDIUMTEXT
21
- from .base import NCHAR
22
- from .base import NUMERIC
23
- from .base import NVARCHAR
24
- from .base import REAL
25
- from .base import SMALLINT
26
- from .base import TEXT
27
- from .base import TIME
28
- from .base import TIMESTAMP
29
- from .base import TINYBLOB
30
- from .base import TINYINT
31
- from .base import TINYTEXT
32
- from .base import VARBINARY
33
- from .base import VARCHAR
34
- from .base import YEAR
4
+ from .base import BIGINT as BIGINT
5
+ from .base import BIT as BIT
6
+ from .base import BLOB as BLOB
7
+ from .base import BOOLEAN as BOOLEAN
8
+ from .base import CHAR as CHAR
9
+ from .base import DATE as DATE
10
+ from .base import DATETIME as DATETIME
11
+ from .base import DECIMAL as DECIMAL
12
+ from .base import DOUBLE as DOUBLE
13
+ from .base import FLOAT as FLOAT
14
+ from .base import INTEGER as INTEGER
15
+ from .base import LONGBLOB as LONGBLOB
16
+ from .base import LONGTEXT as LONGTEXT
17
+ from .base import MEDIUMBLOB as MEDIUMBLOB
18
+ from .base import MEDIUMINT as MEDIUMINT
19
+ from .base import MEDIUMTEXT as MEDIUMTEXT
20
+ from .base import NCHAR as NCHAR
21
+ from .base import NUMERIC as NUMERIC
22
+ from .base import NVARCHAR as NVARCHAR
23
+ from .base import REAL as REAL
24
+ from .base import SMALLINT as SMALLINT
25
+ from .base import TEXT as TEXT
26
+ from .base import TIME as TIME
27
+ from .base import TIMESTAMP as TIMESTAMP
28
+ from .base import TINYBLOB as TINYBLOB
29
+ from .base import TINYINT as TINYINT
30
+ from .base import TINYTEXT as TINYTEXT
31
+ from .base import VARBINARY as VARBINARY
32
+ from .base import VARCHAR as VARCHAR
33
+ from .base import YEAR as YEAR
34
+ from .types import POINT as POINT
35
35
 
36
36
 
37
-
38
- __all__ = (
39
- "BIGINT",
40
- "BINARY",
41
- "BIT",
42
- "BLOB",
43
- "BOOLEAN",
44
- "CHAR",
45
- "DATE",
46
- "DATETIME",
47
- "DECIMAL",
48
- "DOUBLE",
49
- "ENUM",
50
- "FLOAT",
51
- "INET4",
52
- "INET6",
53
- "INTEGER",
54
- "INTEGER",
55
- "JSON",
56
- "LONGBLOB",
57
- "LONGTEXT",
58
- "MEDIUMBLOB",
59
- "MEDIUMINT",
60
- "MEDIUMTEXT",
61
- "NCHAR",
62
- "NVARCHAR",
63
- "NUMERIC",
64
- "SET",
65
- "SMALLINT",
66
- "REAL",
67
- "TEXT",
68
- "TIME",
69
- "TIMESTAMP",
70
- "TINYBLOB",
71
- "TINYINT",
72
- "TINYTEXT",
73
- "VARBINARY",
74
- "VARCHAR",
75
- "YEAR",
76
- "dialect",
77
- "insert",
78
- "Insert",
79
- "match",
80
- )
81
-
37
+ from .repository import MySQLRepository as MySQLRepository # noqa: F401
38
+ from .caster import MySQLCaster as MySQLCaster # noqa: F401
82
39
 
83
40
  # default dialect
84
41
  base.dialect = dialect = mysqlconnector.dialect