database-postgresql-local 0.1.2.1234__tar.gz → 0.1.3b4665__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 (19) hide show
  1. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/PKG-INFO +2 -2
  2. database_postgresql_local-0.1.3b4665/README.md +10 -0
  3. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local/src/connector.py +13 -10
  4. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local/src/cursor.py +12 -8
  5. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local/src/generic_crud_postgresql.py +96 -186
  6. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local/src/table_columns.py +1 -1
  7. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local/src/table_definition.py +1 -1
  8. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local/src/utils.py +15 -15
  9. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local.egg-info/PKG-INFO +2 -2
  10. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local.egg-info/requires.txt +1 -1
  11. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/pyproject.toml +1 -1
  12. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/setup.py +2 -2
  13. database_postgresql_local-0.1.2.1234/README.md +0 -1
  14. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local/src/__init__.py +0 -0
  15. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local/src/constants_src.py +0 -0
  16. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local.egg-info/SOURCES.txt +0 -0
  17. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local.egg-info/dependency_links.txt +0 -0
  18. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/database_postgresql_local.egg-info/top_level.txt +0 -0
  19. {database_postgresql_local-0.1.2.1234 → database_postgresql_local-0.1.3b4665}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: database-postgresql-local
3
- Version: 0.1.2.1234
3
+ Version: 0.1.3b4665
4
4
  Summary: PyPI Package for Circles database-postgresql-local Python
5
5
  Home-page: https://github.com/circles-zone/database-postgresql-local-python-package
6
6
  Author: Circles
@@ -10,7 +10,7 @@ Classifier: Operating System :: OS Independent
10
10
  Description-Content-Type: text/markdown
11
11
  Requires-Dist: python-sdk-remote
12
12
  Requires-Dist: logger-local
13
- Requires-Dist: psycopg2
13
+ Requires-Dist: psycopg2-binary
14
14
  Dynamic: author
15
15
  Dynamic: author-email
16
16
  Dynamic: classifier
@@ -0,0 +1,10 @@
1
+ # Database PostgreSQL Local Python Package
2
+
3
+ TODO Please update the README of the package.<br>
4
+
5
+ ## TODOs
6
+
7
+ TODO dynamic permission to certain columns to certain users.<br>
8
+
9
+ TODO Enforce the GenericCrud interface on GenericCrudPostgres<br>
10
+ TODO Enforce the GenericCrudMl interface on GenericCrudMlPostgres<br>
@@ -2,21 +2,24 @@ from __future__ import annotations # Required for type hinting in class methods
2
2
 
3
3
  from collections import defaultdict
4
4
  from os.path import expanduser
5
- from typing import Optional
5
+ from typing import Any, Optional
6
6
 
7
7
  import psycopg2
8
8
  from psycopg2 import pool
9
+ from logger_local import Logger
9
10
  from logger_local.MetaLogger import MetaLogger
10
11
 
11
12
  from .constants_src import LOGGER_CONNECTOR_CODE_OBJECT
12
- from .cursor import Cursor
13
+ from . import cursor as cursor_module
13
14
  from .utils import (get_sql_hostname, get_sql_password, get_sql_username, get_sql_port)
14
15
 
15
- connections_pool = defaultdict(dict)
16
+ connections_pool: defaultdict[str, dict] = defaultdict(dict)
16
17
  home = expanduser('~')
17
18
 
18
19
 
19
- class Connector(metaclass=MetaLogger, object=LOGGER_CONNECTOR_CODE_OBJECT):
20
+ class Connector(metaclass=MetaLogger, object=LOGGER_CONNECTOR_CODE_OBJECT): # type: ignore[call-arg] # MetaLogger takes `object`
21
+ logger: Logger # Set by MetaLogger
22
+
20
23
  @staticmethod
21
24
  def connect(schema_name: str, *, user: str = get_sql_username(), ignore_cache: bool = False) -> Connector:
22
25
  if ignore_cache and schema_name in connections_pool[user]:
@@ -59,8 +62,8 @@ class Connector(metaclass=MetaLogger, object=LOGGER_CONNECTOR_CODE_OBJECT):
59
62
  if not (self.host.endswith("circ.zone") or self.host.endswith("circlez.ai")):
60
63
  self.logger.warning(
61
64
  f"Your POSTGRESQL_HOSTNAME={self.host} which is not what is expected")
62
- self.connection = None
63
- self._cursor = None
65
+ self.connection: Any = None
66
+ self._cursor: Any = None
64
67
  self._connect_to_db()
65
68
  connections_pool[user][schema_name] = self
66
69
 
@@ -108,12 +111,12 @@ class Connector(metaclass=MetaLogger, object=LOGGER_CONNECTOR_CODE_OBJECT):
108
111
  except:
109
112
  pass
110
113
 
111
- def cursor(self, *, close_previous: bool = True, cache_previous: bool = False, dictionary: bool = None,
112
- buffered: bool = None, raw: bool = None,
113
- prepared: bool = None, named_tuple: bool = None, cursor_class=None) -> Cursor:
114
+ def cursor(self, *, close_previous: bool = True, cache_previous: bool = False, dictionary: Optional[bool] = None,
115
+ buffered: Optional[bool] = None, raw: Optional[bool] = None,
116
+ prepared: Optional[bool] = None, named_tuple: Optional[bool] = None, cursor_class=None) -> cursor_module.Cursor:
114
117
  # PostgreSQL doesn't support all the same cursor options as MySQL
115
118
  # We'll create a basic cursor and wrap it in our Cursor class
116
- cursor_instance = Cursor(self.connection.cursor())
119
+ cursor_instance = cursor_module.Cursor(self.connection.cursor())
117
120
  return cursor_instance
118
121
 
119
122
  def commit(self) -> None:
@@ -1,24 +1,27 @@
1
- from typing import Any
1
+ from typing import Any, Optional
2
2
 
3
+ from logger_local import Logger
3
4
  from logger_local.MetaLogger import MetaLogger
4
5
  from psycopg2.extensions import cursor as PostgreSQLCursor
5
6
  import psycopg2
6
7
  from .constants_src import LOGGER_CONNECTOR_CODE_OBJECT
7
8
 
8
9
  # PostgreSQL version
9
- POSTGRESQL_VERSION = psycopg2.__version__
10
+ POSTGRESQL_VERSION = psycopg2.__version__ # type: ignore[attr-defined] # Not in the psycopg2 type stubs
10
11
 
11
12
 
12
13
  def version_tuple(version):
13
14
  return tuple(map(int, version.split("."))) # Converts "2.9.5" → (2, 9, 5)
14
15
 
15
16
 
16
- class Cursor(metaclass=MetaLogger, object=LOGGER_CONNECTOR_CODE_OBJECT):
17
+ class Cursor(metaclass=MetaLogger, object=LOGGER_CONNECTOR_CODE_OBJECT): # type: ignore[call-arg] # MetaLogger takes `object`
18
+ logger: Logger # Set by MetaLogger
19
+
17
20
  def __init__(self, cursor: PostgreSQLCursor) -> None:
18
21
  self.cursor = cursor
19
22
  self.__is_closed = False
20
23
 
21
- def execute(self, sql_statement: str, sql_parameters: tuple | list = None, multi: bool = False) -> None:
24
+ def execute(self, sql_statement: str, sql_parameters: Optional[tuple | list] = None, multi: bool = False) -> None:
22
25
  # PostgreSQL doesn't support the multi parameter
23
26
  # Convert MySQL-style backtick quotes to PostgreSQL double quotes
24
27
  sql_statement = sql_statement.replace('`', '"')
@@ -43,7 +46,7 @@ class Cursor(metaclass=MetaLogger, object=LOGGER_CONNECTOR_CODE_OBJECT):
43
46
  self.logger.error(f"Error executing SQL: {e}")
44
47
  raise
45
48
 
46
- def executemany(self, sql_statement: str, sql_parameters: tuple | list = None) -> None:
49
+ def executemany(self, sql_statement: str, sql_parameters: Optional[tuple | list] = None) -> None:
47
50
  try:
48
51
  # Convert MySQL-style backtick quotes to PostgreSQL double quotes
49
52
  sql_statement = sql_statement.replace('`', '"')
@@ -61,7 +64,7 @@ class Cursor(metaclass=MetaLogger, object=LOGGER_CONNECTOR_CODE_OBJECT):
61
64
  "sql_statement": sql_statement.replace("\n", " ")
62
65
  })
63
66
 
64
- self.cursor.executemany(sql_statement, sql_parameters)
67
+ self.cursor.executemany(sql_statement, sql_parameters or [])
65
68
  except Exception as e:
66
69
  self.logger.warning('Unable to execute statement', object={
67
70
  "sql_statement": sql_statement,
@@ -82,7 +85,7 @@ class Cursor(metaclass=MetaLogger, object=LOGGER_CONNECTOR_CODE_OBJECT):
82
85
  result = self.cursor.fetchone()
83
86
  return result
84
87
 
85
- def description(self) -> list[tuple]:
88
+ def description(self) -> Optional[tuple]:
86
89
  """Returns description of columns in a result
87
90
 
88
91
  This property returns a list of tuples describing the columns
@@ -112,7 +115,8 @@ class Cursor(metaclass=MetaLogger, object=LOGGER_CONNECTOR_CODE_OBJECT):
112
115
  # This is a simplified implementation that may need to be adjusted based on actual usage
113
116
  try:
114
117
  self.cursor.execute("SELECT lastval()")
115
- result = self.cursor.fetchone()[0]
118
+ row = self.cursor.fetchone()
119
+ result = row[0] if row else None
116
120
  return result
117
121
  except Exception as e:
118
122
  self.logger.warning(f"Error getting lastrowid: {e}")
@@ -1,6 +1,6 @@
1
1
  from datetime import datetime, timezone
2
2
  from functools import lru_cache
3
- from typing import Any, Optional
3
+ from typing import Any, Optional, Sequence
4
4
 
5
5
  import psycopg2
6
6
  from database_infrastructure_local.number_generator import NumberGenerator
@@ -10,13 +10,13 @@ from logger_local.MetaLogger import ABCMetaLogger
10
10
  from user_context_remote.user_context import UserContext
11
11
  from python_sdk_remote.our_object import OurObject
12
12
 
13
- from .connector import Connector
13
+ from . import connector as connector_module
14
14
  from .constants_src import CRUD_POSTGRESQL_CODE_LOGGER_OBJECT
15
- from .cursor import Cursor
15
+ from . import cursor as cursor_module
16
16
  from .table_definition import table_definition
17
17
  from .utils import (detect_if_is_test_data, generate_id_column_name,
18
18
  generate_table_name, generate_view_name,
19
- get_entity_type_id_by_table_name, get_where_params,
19
+ get_entity_type_by_table_name, get_where_params,
20
20
  process_insert_data_dict, process_update_data_dict,
21
21
  process_upsert_data_dict,
22
22
  replace_view_with_table, validate_none_select_table_name,
@@ -31,41 +31,38 @@ from .utils import (detect_if_is_test_data, generate_id_column_name,
31
31
 
32
32
 
33
33
  class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
34
- object=CRUD_POSTGRESQL_CODE_LOGGER_OBJECT):
34
+ object=CRUD_POSTGRESQL_CODE_LOGGER_OBJECT): # type: ignore[call-arg] # MetaLogger takes `object`
35
35
  """A class that provides generic CRUD functionality for PostgreSQL databases.
36
36
  There are 4 main functions to create, read, update, and delete data from the database.
37
37
  The rest of the functions are helper functions or wrappers around the main functions."""
38
38
 
39
39
  def __init__(self, *, default_schema_name: str,
40
- default_table_name: str = None,
41
- default_view_table_name: str = None,
42
- default_view_with_deleted_and_test_data: str = None,
43
- default_column_name: str = None,
40
+ default_table_name: Optional[str] = None,
41
+ default_view_table_name: Optional[str] = None,
42
+ default_view_with_deleted_and_test_data: Optional[str] = None,
43
+ default_column_name: Optional[str] = None,
44
44
  default_select_clause_value: str = "*",
45
- default_where: str = None,
45
+ default_where: Optional[str] = None,
46
46
  is_test_data: bool = False) -> None:
47
47
  """Initializes the GenericCrudPostgresql class. If a connection is not provided, a new connection will be created."""
48
48
  self.default_schema_name = default_schema_name
49
49
  # We do not need a connection per schema, and it makes terrible performance.
50
50
  # In special cases, you can always use set_schema.
51
- self.connection = Connector.connect(schema_name=default_schema_name)
51
+ self.connection = connector_module.Connector.connect(schema_name=default_schema_name)
52
52
  self._cursor = self.connection.cursor()
53
53
  self.default_table_name = default_table_name or generate_table_name(default_schema_name)
54
- self.default_view_table_name = default_view_table_name \
55
- or generate_view_name(
56
- self.default_table_name)
57
- self.default_column_name = default_column_name \
58
- or generate_id_column_name(self.default_table_name)
59
- self.default_view_with_deleted_and_test_data = \
60
- default_view_with_deleted_and_test_data
54
+ self.default_view_table_name = default_view_table_name or generate_view_name(
55
+ self.default_table_name)
56
+ self.default_column_name = default_column_name or generate_id_column_name(self.default_table_name)
57
+ self.default_view_with_deleted_and_test_data = default_view_with_deleted_and_test_data
61
58
  self.default_select_clause_value = default_select_clause_value
62
59
  self.default_where = default_where
63
60
  self.is_test_data = is_test_data or detect_if_is_test_data()
64
61
  self.is_ignore_duplicate = False
65
62
  self.user_context = UserContext()
66
63
 
67
- def insert(self, *, schema_name: str = None, table_name: str = None, data_dict: dict = None,
68
- ignore_duplicate: bool = False, commit_changes: bool = True) -> int:
64
+ def insert(self, *, schema_name: Optional[str] = None, table_name: Optional[str] = None, data_dict: Optional[dict] = None,
65
+ ignore_duplicate: bool = False, commit_changes: bool = True) -> Optional[int]:
69
66
  """Inserts a new row into the table and returns the id of the new row or -1 if an error occurred.
70
67
  ignore_duplicate should be False as default, because for example if a user register with existing name,
71
68
  he should get an error and not existing id
@@ -78,8 +75,7 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
78
75
  object={"data_dict": data_dict})
79
76
 
80
77
  data_dict = self.__add_create_updated_user_profile_ids(
81
- data_dict=data_dict, add_created_user_id=True,
82
- schema_name=schema_name, table_name=table_name)
78
+ data_dict=data_dict, add_created_user_id=True, schema_name=schema_name, table_name=table_name)
83
79
 
84
80
  columns, values, params = process_insert_data_dict(data_dict=data_dict)
85
81
 
@@ -131,9 +127,8 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
131
127
  def __get_existing_duplicate_id_with_undelete(
132
128
  self, schema_name: str, table_name: str, data_dict: dict) -> int | None:
133
129
  column_name = generate_id_column_name(table_name)
134
- where, params = self.get_constraint_where_clause(
135
- schema_name=schema_name, table_name=table_name,
136
- data_dict=data_dict)
130
+ where, params = self.get_constraint_where_clause(schema_name=schema_name, table_name=table_name,
131
+ data_dict=data_dict)
137
132
  row = self.select_one_tuple_by_where(
138
133
  schema_name=schema_name, view_table_name=table_name,
139
134
  select_clause_value=f"{column_name}, end_timestamp",
@@ -175,16 +170,14 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
175
170
  existing_duplicate_id = None
176
171
  else:
177
172
  existing_duplicate_id = self.select_one_value_by_where(
178
- schema_name=schema_name, view_table_name=table_name,
179
- select_clause_value=column_name,
173
+ schema_name=schema_name, view_table_name=table_name, select_clause_value=column_name,
180
174
  where=where, params=params)
181
175
  return existing_duplicate_id
182
-
183
176
  def update_by_column_and_value(
184
- self, *, schema_name: str = None, table_name: str = None,
185
- column_name: str = None, column_value: Any,
186
- data_dict: dict = None,
187
- limit: int = DEFAULT_SQL_SELECT_LIMIT, order_by: str = None,
177
+ self, *, schema_name: Optional[str] = None, table_name: Optional[str] = None,
178
+ column_name: Optional[str] = None, column_value: Any,
179
+ data_dict: Optional[dict] = None,
180
+ limit: int = DEFAULT_SQL_SELECT_LIMIT, order_by: Optional[str] = None,
188
181
  commit_changes: bool = True) -> int:
189
182
  """Updates data in the table by ID."""
190
183
 
@@ -201,96 +194,11 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
201
194
  else:
202
195
  raise Exception("Update by id requires an column_name")
203
196
 
204
- def update_by_where(self, *, schema_name: str = None,
205
- table_name: str = None, where: str = None,
206
- params: tuple = None, data_dict: dict = None,
197
+ def update_by_where(self, *, schema_name: Optional[str] = None,
198
+ table_name: Optional[str] = None, where: Optional[str] = None,
199
+ params: Optional[tuple] = None, data_dict: Optional[dict] = None,
207
200
  limit: int = DEFAULT_SQL_SELECT_LIMIT,
208
- order_by: str = None,
209
- commit_changes: bool = True) -> int:
210
- """Updates data in the table by WHERE.
211
- Example:
212
- "UPDATE table_name SET A=A_val, B=B_val WHERE C=C_val AND D=D_val"
213
- translates into:
214
- update_by_where(table_name="table_name",
215
- data_dict={"A": A_val, "B": B_val},
216
- where="C=%s AND D=%s",
217
- params=(C_val, D_val)"
218
- """
219
-
220
- table_name = table_name or self.default_table_name
221
- schema_name = schema_name or self.default_schema_name
222
- self._validate_args(args=locals())
223
-
224
- data_dict = self.__add_create_updated_user_profile_ids(data_dict=data_dict, add_created_user_id=False,
225
- schema_name=schema_name, table_name=table_name)
226
-
227
- set_values, data_dict_params = process_update_data_dict(data_dict)
228
- if not where:
229
- raise Exception("update_by_where requires a 'where'")
230
-
231
- # PostgreSQL doesn't support LIMIT in UPDATE without a subquery
232
- # We'll handle this differently based on whether limit and order_by are provided
233
- if limit != DEFAULT_SQL_SELECT_LIMIT or order_by:
234
- # For PostgreSQL, we need to use a subquery with LIMIT and ORDER BY
235
- id_column = generate_id_column_name(table_name)
236
-
237
- # First, get the IDs of rows to update
238
- select_query = f'SELECT "{id_column}" FROM "{schema_name}"."{table_name}" WHERE {where}'
239
- if order_by:
240
- select_query += f' ORDER BY {order_by}'
241
- if limit != DEFAULT_SQL_SELECT_LIMIT:
242
- select_query += f' LIMIT {limit}'
243
-
244
- # Then update only those rows
245
- if 'mapping' in self.default_table_name:
246
- update_query = f'UPDATE "{schema_name}"."{table_name}" SET {set_values} ' \
247
- f'WHERE "{id_column}" IN ({select_query});'
248
- else:
249
- update_query = f'UPDATE "{schema_name}"."{table_name}" SET {set_values}, ' \
250
- f'updated_timestamp=CURRENT_TIMESTAMP ' \
251
- f'WHERE "{id_column}" IN ({select_query});'
252
- else:
253
- # Simple update without LIMIT or ORDER BY
254
- if 'mapping' in self.default_table_name:
255
- update_query = f'UPDATE "{schema_name}"."{table_name}" SET {set_values} WHERE {where};'
256
- else:
257
- update_query = f'UPDATE "{schema_name}"."{table_name}" SET {set_values}, ' \
258
- f'updated_timestamp=CURRENT_TIMESTAMP WHERE {where};'
259
-
260
- where_params = params or tuple()
261
-
262
- self.cursor.execute(update_query, data_dict_params + where_params)
263
- if commit_changes:
264
- self.connection.commit()
265
- updated_rows = self.cursor.get_affected_row_count()
266
- return updated_rows
267
-
268
- def update_by_column_and_value(
269
- self, *, schema_name: str = None, table_name: str = None,
270
- column_name: str = None, column_value: Any,
271
- data_dict: dict = None,
272
- limit: int = DEFAULT_SQL_SELECT_LIMIT, order_by: str = None,
273
- commit_changes: bool = True) -> int:
274
- """Updates data in the table by ID."""
275
-
276
- table_name = table_name or self.default_table_name
277
- column_name = column_name or self.default_column_name
278
-
279
- if column_name:
280
- where, params = get_where_params(column_name, column_value)
281
- updated_rows = self.update_by_where(
282
- schema_name=schema_name, table_name=table_name, where=where, data_dict=data_dict,
283
- params=params, limit=limit, order_by=order_by, commit_changes=commit_changes)
284
- return updated_rows
285
-
286
- else:
287
- raise Exception("Update by id requires an column_name")
288
-
289
- def update_by_where(self, *, schema_name: str = None,
290
- table_name: str = None, where: str = None,
291
- params: tuple = None, data_dict: dict = None,
292
- limit: int = DEFAULT_SQL_SELECT_LIMIT,
293
- order_by: str = None,
201
+ order_by: Optional[str] = None,
294
202
  commit_changes: bool = True) -> int:
295
203
  """Updates data in the table by WHERE.
296
204
  Example:
@@ -350,8 +258,8 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
350
258
  updated_rows = self.cursor.get_affected_row_count()
351
259
  return updated_rows
352
260
 
353
- def delete_by_column_and_value(self, *, schema_name: str = None, table_name: str = None,
354
- column_name: str = None, column_value: Any) -> int:
261
+ def delete_by_column_and_value(self, *, schema_name: Optional[str] = None, table_name: Optional[str] = None,
262
+ column_name: Optional[str] = None, column_value: Any) -> int:
355
263
  """Deletes data from the table by id.
356
264
  Returns the number of deleted rows."""
357
265
  # checks are done inside delete_by_where
@@ -365,8 +273,8 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
365
273
  else:
366
274
  raise Exception("Delete by id requires an column_name and column_value.")
367
275
 
368
- def delete_by_where(self, *, schema_name: str = None, table_name: str = None, where: str = None,
369
- params: tuple = None) -> int:
276
+ def delete_by_where(self, *, schema_name: Optional[str] = None, table_name: Optional[str] = None, where: Optional[str] = None,
277
+ params: Optional[tuple] = None) -> int:
370
278
  """Deletes data from the table by WHERE.
371
279
  Returns the number of deleted rows."""
372
280
 
@@ -388,8 +296,8 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
388
296
  deleted_rows = self.cursor.get_affected_row_count()
389
297
  return deleted_rows
390
298
 
391
- def undelete_by_column_and_value(self, *, schema_name: str = None, table_name: str = None,
392
- column_name: str = None, column_value: Any) -> None:
299
+ def undelete_by_column_and_value(self, *, schema_name: Optional[str] = None, table_name: Optional[str] = None,
300
+ column_name: Optional[str] = None, column_value: Any) -> None:
393
301
  """Undeletes a row by setting the end_timestamp to NULL."""
394
302
  schema_name = schema_name or self.default_schema_name
395
303
  table_name = table_name or self.default_table_name
@@ -401,9 +309,9 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
401
309
  data_dict={"end_timestamp": None})
402
310
  # Main select function
403
311
  def select_multi_tuple_by_where(
404
- self, *, schema_name: str = None, view_table_name: str = None, select_clause_value: str = None,
405
- where: str = None, params: tuple = None, distinct: bool = False, limit: int = DEFAULT_SQL_SELECT_LIMIT,
406
- order_by: str = None) -> list:
312
+ self, *, schema_name: Optional[str] = None, view_table_name: Optional[str] = None, select_clause_value: Optional[str] = None,
313
+ where: Optional[str] = None, params: Optional[tuple] = None, distinct: bool = False, limit: int = DEFAULT_SQL_SELECT_LIMIT,
314
+ order_by: Optional[str] = None) -> list:
407
315
  """Selects multiple rows from the table based on a WHERE clause and returns them as a list of tuples."""
408
316
 
409
317
  schema_name = schema_name or self.default_schema_name
@@ -448,21 +356,22 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
448
356
  return result
449
357
 
450
358
  def select_multi_dict_by_where(
451
- self, *, schema_name: str = None, view_table_name: str = None, select_clause_value: str = None,
452
- where: str = None, params: tuple = None, distinct: bool = False, group_by: str = None,
453
- limit: int = DEFAULT_SQL_SELECT_LIMIT, order_by: str = None) -> list | dict[tuple | str, list]:
359
+ self, *, schema_name: Optional[str] = None, view_table_name: Optional[str] = None, select_clause_value: Optional[str] = None,
360
+ where: Optional[str] = None, params: Optional[tuple] = None, distinct: bool = False, group_by: Optional[str] = None,
361
+ limit: int = DEFAULT_SQL_SELECT_LIMIT, order_by: Optional[str] = None) -> list | dict[tuple | str, list]:
454
362
  """Selects multiple rows from the table based on a WHERE clause and returns them as a list of dictionaries."""
455
363
  result = self.select_multi_tuple_by_where(
456
364
  schema_name=schema_name, view_table_name=view_table_name, select_clause_value=select_clause_value,
457
365
  where=where, params=params, distinct=distinct, limit=limit, order_by=order_by)
458
366
  result_as_dicts = self.convert_multi_to_dict(result, select_clause_value)
459
367
  if group_by:
460
- result_as_dicts = group_list_by_columns(list_of_dicts=result_as_dicts, group_by=group_by)
368
+ grouped_result = group_list_by_columns(list_of_dicts=result_as_dicts, group_by=group_by)
369
+ return grouped_result
461
370
  return result_as_dicts
462
371
 
463
372
  def select_one_tuple_by_where(
464
- self, *, schema_name: str = None, view_table_name: str = None, select_clause_value: str = None,
465
- where: str = None, params: tuple = None, distinct: bool = False, order_by: str = None) -> tuple:
373
+ self, *, schema_name: Optional[str] = None, view_table_name: Optional[str] = None, select_clause_value: Optional[str] = None,
374
+ where: Optional[str] = None, params: Optional[tuple] = None, distinct: bool = False, order_by: Optional[str] = None) -> tuple:
466
375
  """Selects one row from the table based on a WHERE clause and returns it as a tuple."""
467
376
  result = self.select_multi_tuple_by_where(
468
377
  schema_name=schema_name, view_table_name=view_table_name, select_clause_value=select_clause_value,
@@ -474,18 +383,18 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
474
383
  return tuple_result
475
384
 
476
385
  def select_one_dict_by_where(
477
- self, *, schema_name: str = None, view_table_name: str = None, select_clause_value: str = None,
478
- where: str = None, params: tuple = None, distinct: bool = False, order_by: str = None) -> dict:
386
+ self, *, schema_name: Optional[str] = None, view_table_name: Optional[str] = None, select_clause_value: Optional[str] = None,
387
+ where: Optional[str] = None, params: Optional[tuple] = None, distinct: bool = False, order_by: Optional[str] = None) -> dict:
479
388
  """Selects one row from the table based on a WHERE clause and returns it as a dictionary."""
480
- result = self.select_one_tuple_by_where(
389
+ row = self.select_one_tuple_by_where(
481
390
  schema_name=schema_name, view_table_name=view_table_name, select_clause_value=select_clause_value,
482
391
  where=where, params=params, distinct=distinct, order_by=order_by)
483
- result = self.convert_to_dict(row=result, select_clause_value=select_clause_value)
392
+ result = self.convert_to_dict(row=row, select_clause_value=select_clause_value)
484
393
  return result
485
394
 
486
395
  def select_one_value_by_where(
487
- self, *, select_clause_value: str, schema_name: str = None, view_table_name: str = None,
488
- where: str = None, params: tuple = None, distinct: bool = False, order_by: str = None,
396
+ self, *, select_clause_value: str, schema_name: Optional[str] = None, view_table_name: Optional[str] = None,
397
+ where: Optional[str] = None, params: Optional[tuple] = None, distinct: bool = False, order_by: Optional[str] = None,
489
398
  skip_null_values: bool = True) -> Any:
490
399
  """Selects one value from the table based on a WHERE clause and returns it."""
491
400
  select_clause_value = select_clause_value or self.default_select_clause_value
@@ -500,9 +409,9 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
500
409
  value = None
501
410
  return value
502
411
  def select_one_tuple_by_column_and_value(
503
- self, *, schema_name: str = None, view_table_name: str = None, select_clause_value: str = None,
504
- column_name: str = None, column_value: Any,
505
- distinct: bool = False, order_by: str = None) -> tuple:
412
+ self, *, schema_name: Optional[str] = None, view_table_name: Optional[str] = None, select_clause_value: Optional[str] = None,
413
+ column_name: Optional[str] = None, column_value: Any,
414
+ distinct: bool = False, order_by: Optional[str] = None) -> tuple:
506
415
  """Selects one row from the table by ID and returns it as a tuple."""
507
416
  result = self.select_multi_tuple_by_column_and_value(
508
417
  schema_name=schema_name, view_table_name=view_table_name, select_clause_value=select_clause_value,
@@ -514,20 +423,20 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
514
423
  return one_tuple_result
515
424
 
516
425
  def select_one_dict_by_column_and_value(
517
- self, *, schema_name: str = None, view_table_name: str = None, select_clause_value: str = None,
518
- column_name: str = None, column_value: Any,
519
- distinct: bool = False, order_by: str = None) -> dict:
426
+ self, *, schema_name: Optional[str] = None, view_table_name: Optional[str] = None, select_clause_value: Optional[str] = None,
427
+ column_name: Optional[str] = None, column_value: Any,
428
+ distinct: bool = False, order_by: Optional[str] = None) -> dict:
520
429
  """Selects one row from the table by ID and returns it as a dictionary (column_name: value)"""
521
- result = self.select_one_tuple_by_column_and_value(
430
+ row = self.select_one_tuple_by_column_and_value(
522
431
  schema_name=schema_name, view_table_name=view_table_name, select_clause_value=select_clause_value,
523
432
  column_name=column_name, column_value=column_value, distinct=distinct, order_by=order_by)
524
- result = self.convert_to_dict(row=result, select_clause_value=select_clause_value)
433
+ result = self.convert_to_dict(row=row, select_clause_value=select_clause_value)
525
434
  return result
526
435
 
527
436
  def select_one_value_by_column_and_value(
528
- self, *, select_clause_value: str = None, schema_name: str = None, view_table_name: str = None,
529
- column_name: str = None, column_value: Any,
530
- distinct: bool = False, order_by: str = None, skip_null_values: bool = True) -> Any:
437
+ self, *, select_clause_value: Optional[str] = None, schema_name: Optional[str] = None, view_table_name: Optional[str] = None,
438
+ column_name: Optional[str] = None, column_value: Any,
439
+ distinct: bool = False, order_by: Optional[str] = None, skip_null_values: bool = True) -> Any:
531
440
  """Selects one value from the table by ID and returns it."""
532
441
 
533
442
  column_name = column_name or self.default_column_name
@@ -545,9 +454,9 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
545
454
  return value
546
455
 
547
456
  def select_multi_tuple_by_column_and_value(
548
- self, *, schema_name: str = None, view_table_name: str = None, select_clause_value: str = None,
549
- column_name: str = None, column_value: Any,
550
- distinct: bool = False, limit: int = DEFAULT_SQL_SELECT_LIMIT, order_by: str = None) -> list:
457
+ self, *, schema_name: Optional[str] = None, view_table_name: Optional[str] = None, select_clause_value: Optional[str] = None,
458
+ column_name: Optional[str] = None, column_value: Any,
459
+ distinct: bool = False, limit: int = DEFAULT_SQL_SELECT_LIMIT, order_by: Optional[str] = None) -> list:
551
460
  """Selects multiple rows from the table by ID and returns them as a list of tuples.
552
461
  If column_value is list / tuple, it will be used as multiple values for the column_name (SQL IN)."""
553
462
 
@@ -560,20 +469,21 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
560
469
  return result
561
470
 
562
471
  def select_multi_dict_by_column_and_value(
563
- self, *, schema_name: str = None, view_table_name: str = None, select_clause_value: str = None,
564
- column_name: str = None, column_value: Any,
565
- distinct: bool = False, limit: int = DEFAULT_SQL_SELECT_LIMIT, order_by: str = None,
566
- group_by: str = None) -> list | dict[tuple | str, list]:
472
+ self, *, schema_name: Optional[str] = None, view_table_name: Optional[str] = None, select_clause_value: Optional[str] = None,
473
+ column_name: Optional[str] = None, column_value: Any,
474
+ distinct: bool = False, limit: int = DEFAULT_SQL_SELECT_LIMIT, order_by: Optional[str] = None,
475
+ group_by: Optional[str] = None) -> list | dict[tuple | str, list]:
567
476
  """Selects multiple rows from the table by ID and returns them as a list of dictionaries."""
568
477
  result = self.select_multi_tuple_by_column_and_value(
569
478
  schema_name=schema_name, view_table_name=view_table_name, select_clause_value=select_clause_value,
570
479
  column_name=column_name, column_value=column_value, distinct=distinct, limit=limit, order_by=order_by)
571
480
  result_as_dicts = self.convert_multi_to_dict(result, select_clause_value)
572
481
  if group_by:
573
- result_as_dicts = group_list_by_columns(list_of_dicts=result_as_dicts, group_by=group_by)
482
+ grouped_result = group_list_by_columns(list_of_dicts=result_as_dicts, group_by=group_by)
483
+ return grouped_result
574
484
  return result_as_dicts
575
- def insert_if_not_exists(self, *, schema_name: str = None, table_name: str = None, data_dict: dict = None,
576
- data_dict_compare: dict = None, view_table_name: str = None,
485
+ def insert_if_not_exists(self, *, schema_name: Optional[str] = None, table_name: Optional[str] = None, data_dict: Optional[dict] = None,
486
+ data_dict_compare: Optional[dict] = None, view_table_name: Optional[str] = None,
577
487
  commit_changes: bool = True, compare_with_or: bool = False) -> int:
578
488
  """Inserts a new row into the table if a row with the same values does not exist,
579
489
  and returns the id of the new row | None if an error occurred."""
@@ -584,7 +494,7 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
584
494
  self._validate_args(args=locals())
585
495
 
586
496
  # Try to select
587
- where_clause, params = process_upsert_data_dict(data_dict=data_dict_compare, compare_with_or=compare_with_or)
497
+ where_clause, params = process_upsert_data_dict(data_dict=data_dict_compare or {}, compare_with_or=compare_with_or)
588
498
  row_tuple = self.select_one_tuple_by_where(
589
499
  schema_name=schema_name, view_table_name=view_table_name, select_clause_value="*",
590
500
  where=where_clause, params=params)
@@ -599,7 +509,7 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
599
509
  object={"id": entity_id})
600
510
  return entity_id
601
511
 
602
- def insert_many_dicts(self, *, schema_name: str = None, table_name: str = None, data_dicts: list[dict],
512
+ def insert_many_dicts(self, *, schema_name: Optional[str] = None, table_name: Optional[str] = None, data_dicts: list[dict],
603
513
  commit_changes: bool = True) -> int:
604
514
  """Inserts multiple rows into the table.
605
515
  data_dicts should be in the following format: [{col1: val1, col2: val2}, {col1: val3, col2: val4}, ...]
@@ -609,13 +519,13 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
609
519
  self.logger.warning("GenericCrudPostgresql.insert_many_dicts: data_dicts is empty")
610
520
  inserted_rows = 0
611
521
  else:
612
- converted_data_dicts = {col: [row[col] for row in data_dicts] for col in data_dicts[0]}
522
+ converted_data_dicts: dict[str, list[Any] | tuple[Any, ...]] = {col: [row[col] for row in data_dicts] for col in data_dicts[0]}
613
523
  inserted_rows = self.insert_many(schema_name=schema_name, table_name=table_name,
614
524
  data_dict=converted_data_dicts, commit_changes=commit_changes)
615
525
 
616
526
  return inserted_rows
617
527
 
618
- def insert_many(self, *, schema_name: str = None, table_name: str = None, data_dict: dict[str, list | tuple],
528
+ def insert_many(self, *, schema_name: Optional[str] = None, table_name: Optional[str] = None, data_dict: dict[str, list | tuple],
619
529
  commit_changes: bool = True) -> int:
620
530
  """Inserts multiple rows into the table.
621
531
  data_dict should be in the following format: {col1: [val1, val2], col2: [val3, val4], ...}
@@ -648,9 +558,9 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
648
558
  self.connection.commit()
649
559
  inserted_rows = self.cursor.get_affected_row_count()
650
560
  return inserted_rows
651
- def upsert_with_select_clause(self, *, schema_name: str = None, table_name: str = None, view_table_name: str = None,
652
- data_dict: dict = None, where_compare: str = None, params_compare: tuple = None,
653
- data_dict_compare: dict = None, order_by: str = None, compare_with_or: bool = False,
561
+ def upsert_with_select_clause(self, *, schema_name: Optional[str] = None, table_name: Optional[str] = None, view_table_name: Optional[str] = None,
562
+ data_dict: Optional[dict] = None, where_compare: Optional[str] = None, params_compare: Optional[tuple] = None,
563
+ data_dict_compare: Optional[dict] = None, order_by: Optional[str] = None, compare_with_or: bool = False,
654
564
  select_clause_value: str = "*") -> dict:
655
565
  """
656
566
  Inserts a new row into the table if a row with the same values does not exist,
@@ -667,7 +577,7 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
667
577
  view_table_name = view_table_name or self.default_view_table_name
668
578
  column_name = generate_id_column_name(table_name)
669
579
  self._validate_args(args=locals())
670
- result_dict = {}
580
+ result_dict: dict = {}
671
581
  if not data_dict:
672
582
  self.logger.warning(log_message="GenericCrudPostgresql.upsert_with_select_clause: data_dict is empty")
673
583
  return result_dict
@@ -678,7 +588,7 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
678
588
  result_dict = data_dict
679
589
  return result_dict
680
590
 
681
- where_clause, params = process_upsert_data_dict(data_dict=data_dict_compare, compare_with_or=compare_with_or,
591
+ where_clause, params = process_upsert_data_dict(data_dict=data_dict_compare or {}, compare_with_or=compare_with_or,
682
592
  where_compare=where_compare, params_compare=params_compare)
683
593
  # Add table_id if it's not in select_clause_value
684
594
  if select_clause_value != "*" and column_name not in select_clause_value:
@@ -714,10 +624,10 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
714
624
  return result_dict
715
625
 
716
626
  # We want upsert to call upsert_with_select_clause, and return only the id
717
- def upsert(self, *, schema_name: str = None, table_name: str = None, view_table_name: str = None,
718
- data_dict: dict = None, where_compare: str = None,
719
- params_compare: tuple = None, data_dict_compare: dict = None,
720
- order_by: str = None, compare_with_or: bool = False) -> Optional[int]:
627
+ def upsert(self, *, schema_name: Optional[str] = None, table_name: Optional[str] = None, view_table_name: Optional[str] = None,
628
+ data_dict: Optional[dict] = None, where_compare: Optional[str] = None,
629
+ params_compare: Optional[tuple] = None, data_dict_compare: Optional[dict] = None,
630
+ order_by: Optional[str] = None, compare_with_or: bool = False) -> Optional[int]:
721
631
  """
722
632
  Inserts a new row into the table if a row with the same values does not exist,
723
633
  the "same values" are extracted from data_dict_compare.
@@ -736,18 +646,18 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
736
646
  inserted_id = inserted_id_per_column_dict[column_name]
737
647
  return inserted_id
738
648
  # Helper methods
739
- def convert_to_dict(self, row: tuple, select_clause_value: str = None) -> dict:
649
+ def convert_to_dict(self, row: tuple, select_clause_value: Optional[str] = None) -> dict:
740
650
  """Returns a dictionary of the column names and their values."""
741
651
  select_clause_value = select_clause_value or self.default_select_clause_value
742
652
  if select_clause_value == "*":
743
- column_names = self.cursor.column_names()
653
+ column_names: Sequence[str] = self.cursor.column_names()
744
654
  else:
745
655
  column_names = [x.strip() for x in select_clause_value.split(",")]
746
656
  dict_result = dict(zip(column_names, row or tuple()))
747
657
  self.logger.debug(object=locals())
748
658
  return dict_result
749
659
 
750
- def convert_multi_to_dict(self, rows: list[tuple], select_clause_value: str = None) -> list[dict]:
660
+ def convert_multi_to_dict(self, rows: list[tuple], select_clause_value: Optional[str] = None) -> list[dict]:
751
661
  """Converts multiple rows to dictionaries."""
752
662
  multiple_dict_result = [self.convert_to_dict(row=row, select_clause_value=select_clause_value)
753
663
  for row in rows]
@@ -777,7 +687,7 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
777
687
  if message:
778
688
  raise Exception(message)
779
689
 
780
- def __where_security(self, where: str, view_name: str) -> str:
690
+ def __where_security(self, where: Optional[str], view_name: str) -> Optional[str]:
781
691
  """Adds security to the where clause."""
782
692
  if view_name in table_definition:
783
693
  if table_definition[view_name].get("is_visibility"):
@@ -788,8 +698,8 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
788
698
  return where_security
789
699
  return where
790
700
 
791
- def __add_create_updated_user_profile_ids(self, data_dict: dict, add_created_user_id: bool = False,
792
- schema_name: str = None, table_name: str = None) -> dict:
701
+ def __add_create_updated_user_profile_ids(self, data_dict: Optional[dict], add_created_user_id: bool = False,
702
+ schema_name: Optional[str] = None, table_name: Optional[str] = None) -> dict:
793
703
  """Adds created_user_id and updated_user_id to data_dict."""
794
704
  data_dict = data_dict or {}
795
705
  schema_name = schema_name or self.default_schema_name
@@ -859,7 +769,7 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
859
769
 
860
770
  def __add_identifier(self, data_dict: dict, table_name: str) -> None:
861
771
  # If there's an "identifier" column in the table, we want to insert a random identifier
862
- identifier_entity_type_id = get_entity_type_id_by_table_name(table_name)
772
+ identifier_entity_type_id = get_entity_type_by_table_name(table_name)
863
773
  if not identifier_entity_type_id:
864
774
  return
865
775
  identifier = NumberGenerator.get_random_identifier(
@@ -871,7 +781,7 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
871
781
  self.connection.commit()
872
782
 
873
783
  @lru_cache
874
- def get_primary_key(self, schema_name: str = None, table_name: str = None) -> str | None:
784
+ def get_primary_key(self, schema_name: Optional[str] = None, table_name: Optional[str] = None) -> str | None:
875
785
  schema_name = schema_name or self.default_schema_name
876
786
  table_name = table_name or self.default_table_name
877
787
  query = """
@@ -929,7 +839,7 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
929
839
  return where, params
930
840
 
931
841
  @property
932
- def cursor(self) -> Cursor:
842
+ def cursor(self) -> cursor_module.Cursor:
933
843
  """Get a new cursor"""
934
844
  if self._cursor.is_closed():
935
845
  self._cursor = self.connection.cursor()
@@ -937,7 +847,7 @@ class GenericCrudPostgresql(GenericCrudAbstract, metaclass=ABCMetaLogger,
937
847
  return cursor
938
848
 
939
849
  @cursor.setter
940
- def cursor(self, value: Cursor) -> None:
850
+ def cursor(self, value: cursor_module.Cursor) -> None:
941
851
  """Set the cursor"""
942
852
  self._cursor = value
943
853
 
@@ -1,4 +1,4 @@
1
1
  # Placeholder for table columns
2
2
  # This will be populated from the database schema
3
3
 
4
- table_columns = {}
4
+ table_columns: dict = {}
@@ -1,4 +1,4 @@
1
1
  # Placeholder for table definitions
2
2
  # This will be populated from the database schema
3
3
 
4
- table_definition = {}
4
+ table_definition: dict = {}
@@ -82,7 +82,7 @@ def generate_view_name(table_name: str) -> str:
82
82
  return f"{table_name}_view"
83
83
 
84
84
 
85
- def get_entity_type_id_by_table_name(table_name: str) -> int:
85
+ def get_entity_type_by_table_name(table_name: str) -> Optional[int]:
86
86
  """Gets the entity type ID for a table."""
87
87
  # This would be implemented based on your entity type mapping
88
88
  return None
@@ -116,27 +116,27 @@ def process_update_data_dict(data_dict: dict) -> tuple:
116
116
 
117
117
 
118
118
  def process_upsert_data_dict(data_dict: dict, compare_with_or: bool = False,
119
- where_compare: str = None, params_compare: tuple = None) -> tuple:
119
+ where_compare: Optional[str] = None, params_compare: Optional[tuple] = None) -> tuple:
120
120
  """Processes a dictionary for an UPSERT statement."""
121
121
  if where_compare:
122
122
  where = where_compare
123
123
  params = params_compare
124
124
  else:
125
125
  where_parts = []
126
- params = []
126
+ params_list = []
127
127
  for key, value in data_dict.items():
128
128
  if value is None:
129
129
  where_parts.append(f"\"{key}\" IS NULL")
130
130
  else:
131
131
  where_parts.append(f"\"{key}\" = %s")
132
- params.append(value)
132
+ params_list.append(value)
133
133
  connector = " OR " if compare_with_or else " AND "
134
134
  where = connector.join(where_parts)
135
- params = tuple(params)
135
+ params = tuple(params_list)
136
136
  return where, params
137
137
 
138
138
 
139
- def replace_view_with_table(view_table_name: str, select_clause_value: str = None) -> str:
139
+ def replace_view_with_table(view_table_name: str, select_clause_value: Optional[str] = None) -> str:
140
140
  """Replaces a view name with a table name."""
141
141
  if view_table_name.endswith('_view'):
142
142
  return view_table_name[:-5] + '_table'
@@ -161,7 +161,7 @@ def validate_single_clause_value(select_clause_value: str) -> None:
161
161
  raise ValueError(f"Expected a single column, got: {select_clause_value}")
162
162
 
163
163
 
164
- def where_skip_null_values(where: str, select_clause_value: str, skip_null_values: bool) -> str:
164
+ def where_skip_null_values(where: Optional[str], select_clause_value: str, skip_null_values: bool) -> Optional[str]:
165
165
  """Adds a condition to skip NULL values in a WHERE clause."""
166
166
  if skip_null_values:
167
167
  null_condition = f"{select_clause_value} IS NOT NULL"
@@ -199,7 +199,7 @@ def get_table_columns(table_name: str) -> list:
199
199
 
200
200
  def group_list_by_columns(list_of_dicts: list, group_by: str) -> dict:
201
201
  """Groups a list of dictionaries by specified columns."""
202
- result = {}
202
+ result: dict = {}
203
203
  group_by_columns = [col.strip() for col in group_by.split(',')]
204
204
 
205
205
  for item in list_of_dicts:
@@ -217,15 +217,15 @@ def group_list_by_columns(list_of_dicts: list, group_by: str) -> dict:
217
217
  def process_select_data_dict(data_dict: dict) -> tuple:
218
218
  """Processes a dictionary for a SELECT statement."""
219
219
  where_parts = []
220
- params = []
220
+ params_list = []
221
221
  for key, value in data_dict.items():
222
222
  if value is None:
223
223
  where_parts.append(f"\"{key}\" IS NULL")
224
224
  else:
225
225
  where_parts.append(f"\"{key}\" = %s")
226
- params.append(value)
226
+ params_list.append(value)
227
227
  where = " AND ".join(where_parts)
228
- params = tuple(params)
228
+ params = tuple(params_list)
229
229
  return where, params
230
230
 
231
231
 
@@ -233,7 +233,7 @@ def generate_where_clause_for_ignore_duplicate(data_dict: dict, constraint_colum
233
233
  """Generates a WHERE clause for checking duplicates."""
234
234
  for columns in constraint_columns:
235
235
  where_parts = []
236
- params = []
236
+ params_list = []
237
237
  valid = True
238
238
  for column in columns:
239
239
  if column in data_dict:
@@ -242,13 +242,13 @@ def generate_where_clause_for_ignore_duplicate(data_dict: dict, constraint_colum
242
242
  where_parts.append(f"\"{column}\" IS NULL")
243
243
  else:
244
244
  where_parts.append(f"\"{column}\" = %s")
245
- params.append(value)
245
+ params_list.append(value)
246
246
  else:
247
247
  valid = False
248
248
  break
249
249
  if valid and where_parts:
250
250
  where = " AND ".join(where_parts)
251
- params = tuple(params)
251
+ params = tuple(params_list)
252
252
  return where, params
253
253
  return None, None
254
254
 
@@ -258,6 +258,6 @@ def fix_select_clause_value(select_clause_value: str) -> str:
258
258
  return select_clause_value
259
259
 
260
260
 
261
- def fix_where_clause_value(where_clause_value: str) -> str:
261
+ def fix_where_clause_value(where_clause_value: Optional[str]) -> Optional[str]:
262
262
  """Fixes a WHERE clause value."""
263
263
  return where_clause_value
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: database-postgresql-local
3
- Version: 0.1.2.1234
3
+ Version: 0.1.3b4665
4
4
  Summary: PyPI Package for Circles database-postgresql-local Python
5
5
  Home-page: https://github.com/circles-zone/database-postgresql-local-python-package
6
6
  Author: Circles
@@ -10,7 +10,7 @@ Classifier: Operating System :: OS Independent
10
10
  Description-Content-Type: text/markdown
11
11
  Requires-Dist: python-sdk-remote
12
12
  Requires-Dist: logger-local
13
- Requires-Dist: psycopg2
13
+ Requires-Dist: psycopg2-binary
14
14
  Dynamic: author
15
15
  Dynamic: author-email
16
16
  Dynamic: classifier
@@ -1,3 +1,3 @@
1
1
  python-sdk-remote
2
2
  logger-local
3
- psycopg2
3
+ psycopg2-binary
@@ -14,7 +14,7 @@ build-backend = "setuptools.build_meta"
14
14
  # TODO: Please update the name, similar to storage-local (suffix -local)
15
15
  name = "<project-name>"
16
16
  # I believe we are still using the version from setup.py and not from here until Potery will work
17
- version = "0.0.1" # https://pypi.org/project/<project-name> i.e. https://pypi.org/project/storage-local/
17
+ version = "0.1.3b4665" # https://pypi.org/project/<project-name> i.e. https://pypi.org/project/storage-local/
18
18
  description = "<project-name> Python Package"
19
19
  readme = "README.md"
20
20
  authors = [
@@ -24,7 +24,7 @@ setuptools.setup(
24
24
  name=PACKAGE_NAME,
25
25
  # Increase this number every time you make a change you
26
26
  # want to publish. After 0.0.9 switch to 0.0.10 and not 0.1.0
27
- version='0.1.2.1234', # https://pypi.org/project/database-postgresql-local/
27
+ version='0.1.3b4665', # https://pypi.org/project/database-postgresql-local/
28
28
  author="Circles",
29
29
  author_email="info@circlez.ai",
30
30
  description=f"PyPI Package for Circles {PACKAGE_NAME} Python",
@@ -58,6 +58,6 @@ setuptools.setup(
58
58
  # TODO: in -remote package please use logger-remote instead.
59
59
  'logger-local',
60
60
  # TODO: In -remote package please delete this line.
61
- 'psycopg2'
61
+ 'psycopg2-binary'
62
62
  ]
63
63
  )
@@ -1 +0,0 @@
1
- TODO Please update the README of the package