python-general-be-lib 0.5.1__tar.gz → 0.5.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/PKG-INFO +1 -1
  2. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/repository/handler/__init__.py +1 -0
  3. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/repository/handler/interval_handler.py +9 -4
  4. python_general_be_lib-0.5.3/general/interface/repository/handler/json_ilike_handler.py +104 -0
  5. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/pyproject.toml +1 -1
  6. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/python_general_be_lib.egg-info/PKG-INFO +1 -1
  7. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/python_general_be_lib.egg-info/SOURCES.txt +1 -0
  8. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/setup.py +2 -2
  9. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/LICENSE +0 -0
  10. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/README.md +0 -0
  11. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/__init__.py +0 -0
  12. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/exception/__init__.py +0 -0
  13. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/exception/access_exceptions.py +0 -0
  14. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/exception/crud_exceptions.py +0 -0
  15. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/exception/exception_interface.py +0 -0
  16. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/base/__init__.py +0 -0
  17. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/base/base_model.py +0 -0
  18. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/base/declarative_base.py +0 -0
  19. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/metadata/__init__.py +0 -0
  20. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/metadata/crud_metadata.py +0 -0
  21. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/metadata/geom_metadata.py +0 -0
  22. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/repository/__init__.py +0 -0
  23. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/repository/crud_repository.py +0 -0
  24. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/repository/geometry_repository.py +0 -0
  25. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/repository/handler/base_handler.py +0 -0
  26. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/repository/handler/ilike_handler.py +0 -0
  27. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/repository/handler/json_handler.py +0 -0
  28. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/repository/handler/statement_manager.py +0 -0
  29. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/repository/many_to_many_repository.py +0 -0
  30. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/interface/repository/view_repository.py +0 -0
  31. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/logger.py +0 -0
  32. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/general/paginator_dto.py +0 -0
  33. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/python_general_be_lib.egg-info/dependency_links.txt +0 -0
  34. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/python_general_be_lib.egg-info/requires.txt +0 -0
  35. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/python_general_be_lib.egg-info/top_level.txt +0 -0
  36. {python_general_be_lib-0.5.1 → python_general_be_lib-0.5.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-general-be-lib
3
- Version: 0.5.1
3
+ Version: 0.5.3
4
4
  Summary: General purpose backend library — SQLAlchemy CRUD/Geometry repositories, FastAPI exceptions, Pydantic base models, logger utilities.
5
5
  Author-email: Andrea Di Placido <a.diplacido@arpes.it>, "Arpes S.r.l." <it.admin@arpes.it>
6
6
  License: MIT
@@ -2,4 +2,5 @@ from .base_handler import *
2
2
  from .ilike_handler import *
3
3
  from .interval_handler import *
4
4
  from .json_handler import *
5
+ from .json_ilike_handler import *
5
6
  from .statement_manager import *
@@ -31,12 +31,14 @@ class IntervalHandler(BaseHandler):
31
31
  >>> repo.find(where={"start_date": "2024-01-01", "end_date": "2024-12-31"})
32
32
  # WHERE start_date >= '2024-01-01' AND (end_date <= '2024-12-31' OR end_date IS NULL)
33
33
  """
34
- __slots__ = "from_", "to_", "inf_is_none"
34
+ __slots__ = "from_", "to_", "inf_is_none", "from_alias", "to_alias", "between"
35
35
  from_: Any
36
36
  to_: Any
37
+ from_alias: str
38
+ to_alias: str
37
39
  inf_is_none: bool
38
40
 
39
- def __init__(self, columns: ReadOnlyColumnCollection[str, Column[Any]], from_: Any = None, to_: Any = None, inf_is_none: bool = False):
41
+ def __init__(self, columns: ReadOnlyColumnCollection[str, Column[Any]], from_: Any = None, from_alias: str = None, to_: Any = None, to_alias: str = None, inf_is_none: bool = False):
40
42
  """Inizializza l'handler con le chiavi per il limite inferiore e superiore.
41
43
 
42
44
  Args:
@@ -52,7 +54,10 @@ class IntervalHandler(BaseHandler):
52
54
  self.columns = columns
53
55
  self.from_ = from_
54
56
  self.to_ = to_
57
+ self.from_alias = from_alias if from_alias else str(from_)
58
+ self.to_alias = to_alias if to_alias else str(to_)
55
59
  self.inf_is_none = inf_is_none
60
+ self.between = True if self.from_alias == self.to_alias else False
56
61
 
57
62
  def handle(self, stmt: Select | Update | Delete, where: dict[str, Any] = None, **kwargs):
58
63
  """Applica le condizioni di range allo statement estraendo i valori da ``where``.
@@ -75,8 +80,8 @@ class IntervalHandler(BaseHandler):
75
80
  - Limite superiore: ``col <= value`` oppure ``(col <= value OR col IS NULL)``
76
81
  se ``inf_is_none=True``.
77
82
  """
78
- from_condition = where.pop(self.from_, None)
79
- to_condition = where.pop(self.to_, None)
83
+ from_condition = where.pop(self.from_alias, None)
84
+ to_condition = where.pop(self.to_alias, None) if not self.between else from_condition
80
85
  if from_condition:
81
86
  stmt = stmt.where(self.columns[self.from_] >= from_condition)
82
87
  if to_condition:
@@ -0,0 +1,104 @@
1
+ __all__ = ["JsonILikeHandler"]
2
+
3
+ from typing import Any
4
+
5
+ from general.interface.repository.handler import BaseHandler
6
+ from sqlalchemy import Column, Select, Update, Delete, or_
7
+ from sqlalchemy.sql.base import ReadOnlyColumnCollection
8
+
9
+
10
+ class JsonILikeHandler(BaseHandler):
11
+ """Handler per ricerche case-insensitive (ILIKE) su più colonne tramite un alias.
12
+
13
+ Permette di esporre un singolo parametro di ricerca testuale (es. ``"search"``)
14
+ che viene applicato come ``ILIKE '%value%'`` su un insieme di colonne con ``OR``.
15
+
16
+ Attributes:
17
+ ilike_aliases (list[str]): Chiavi nel dizionario ``where`` che attivano
18
+ la ricerca ILIKE (es. ``["search", "q"]``).
19
+ ilike_attributes (list[str]): Nomi delle colonne su cui applicare ILIKE
20
+ (es. ``["name", "surname", "email"]``).
21
+
22
+ Example:
23
+ >>> handler = JsonILikeHandler(
24
+ ... columns=User.columns(),
25
+ ... ilike_aliases=["search"],
26
+ ... ilike_attributes=["name", "surname"]
27
+ ... )
28
+ >>> repo.find(where={"search": "mario"})
29
+ # WHERE name ILIKE '%mario%' OR surname ILIKE '%mario%'
30
+ """
31
+ __slots__ = "ilike_aliases", "ilike_attributes", "json_column", "json_ilike_keys"
32
+ ilike_aliases: list[str]
33
+ ilike_attributes: list[str]
34
+ json_ilike_keys: list[str]
35
+ json_column: str
36
+
37
+ def __init__(self, columns: ReadOnlyColumnCollection[str, Column[Any]], ilike_aliases: list[str] = None, ilike_attributes: list[str] = None):
38
+ """Inizializza l'handler validando che le colonne ILIKE esistano sull'entità.
39
+
40
+ Args:
41
+ columns (ReadOnlyColumnCollection): Colonne della tabella.
42
+ ilike_aliases (list[str], optional): Chiavi alias che attivano la ricerca.
43
+ Default: lista vuota.
44
+ ilike_attributes (list[str], optional): Colonne su cui applicare ILIKE.
45
+ Default: lista vuota.
46
+
47
+ Raises:
48
+ ValueError: Se uno degli ``ilike_attributes`` non è presente tra le colonne.
49
+ """
50
+ self.columns = columns
51
+ self.ilike_aliases = ilike_aliases if ilike_aliases is not None else []
52
+ self.ilike_attributes = []
53
+ self.json_ilike_keys = []
54
+
55
+ if ilike_attributes:
56
+ for ilike_attribute in ilike_attributes:
57
+ if ilike_attribute not in self.columns:
58
+ self.json_ilike_keys.append(ilike_attribute)
59
+ else:
60
+ self.ilike_attributes.append(ilike_attribute)
61
+
62
+ for key, column in columns.items():
63
+ try:
64
+ if column.type.python_type == dict:
65
+ self.json_column = key
66
+ break
67
+ except NotImplementedError:
68
+ continue
69
+
70
+ def handle(self, stmt: Select | Update | Delete, where: dict[str, Any] = None, **kwargs):
71
+ """Applica i filtri ILIKE allo statement per ogni alias trovato in ``where``.
72
+
73
+ Per ogni alias presente in ``ilike_aliases`` e trovato in ``where``,
74
+ estrae il valore, lo rimuove dal dizionario e aggiunge la condizione ILIKE
75
+ su tutte le colonne in ``ilike_attributes`` con ``OR``.
76
+
77
+ Args:
78
+ stmt (Select | Update | Delete): Statement su cui applicare i filtri.
79
+ where (dict[str, Any]): Dizionario dei filtri. Gli alias ILIKE vengono
80
+ estratti e rimossi in-place.
81
+ **kwargs: Ignorati (compatibilità con l'interfaccia base).
82
+
83
+ Returns:
84
+ Select | Update | Delete: Statement con le condizioni ILIKE aggiunte.
85
+ """
86
+
87
+ for alias in self.ilike_aliases:
88
+ condition = where.pop(alias, None)
89
+ if condition:
90
+ stmt = stmt.where(self._handle(alias, condition))
91
+ return stmt
92
+
93
+ def _handle(self, alias: str, condition: str, neq: bool = False):
94
+ """Costruisce la condizione ILIKE con OR su tutte le colonne configurate.
95
+
96
+ Args:
97
+ alias (str): Alias attivato (usato per identificare la ricerca, non la colonna).
98
+ condition (str): Stringa da cercare (viene wrappata con ``%``).
99
+ neq (bool): Non utilizzato in questa implementazione.
100
+
101
+ Returns:
102
+ ColumnElement: Espressione ``OR(col1 ILIKE '%val%', col2 ILIKE '%val%', ...)``.
103
+ """
104
+ return or_(*[self.columns[col].ilike(f'%{condition}%') for col in self.ilike_attributes], *[self.columns[self.json_column][key].as_string().ilike(f'%{condition}%') for key in self.json_ilike_keys])
@@ -4,7 +4,7 @@ build-backend = "setuptools.backends.legacy:build"
4
4
 
5
5
  [project]
6
6
  name = "python-general-be-lib"
7
- version = "0.5.1"
7
+ version = "0.5.3"
8
8
  description = "General purpose backend library — SQLAlchemy CRUD/Geometry repositories, FastAPI exceptions, Pydantic base models, logger utilities."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-general-be-lib
3
- Version: 0.5.1
3
+ Version: 0.5.3
4
4
  Summary: General purpose backend library — SQLAlchemy CRUD/Geometry repositories, FastAPI exceptions, Pydantic base models, logger utilities.
5
5
  Author-email: Andrea Di Placido <a.diplacido@arpes.it>, "Arpes S.r.l." <it.admin@arpes.it>
6
6
  License: MIT
@@ -25,6 +25,7 @@ general/interface/repository/handler/base_handler.py
25
25
  general/interface/repository/handler/ilike_handler.py
26
26
  general/interface/repository/handler/interval_handler.py
27
27
  general/interface/repository/handler/json_handler.py
28
+ general/interface/repository/handler/json_ilike_handler.py
28
29
  general/interface/repository/handler/statement_manager.py
29
30
  python_general_be_lib.egg-info/PKG-INFO
30
31
  python_general_be_lib.egg-info/SOURCES.txt
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="python-general-be-lib",
5
- version="0.5.1",
5
+ version="0.5.3",
6
6
  packages=find_packages(include=["general*"]),
7
7
  python_requires=">=3.12",
8
8
  install_requires=[
@@ -11,4 +11,4 @@ setup(
11
11
  "sqlalchemy>=2.0.0",
12
12
  "geoalchemy2>=0.14.0",
13
13
  ],
14
- )
14
+ )