t-sql 4.1.0__tar.gz → 4.2.0__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 (31) hide show
  1. {t_sql-4.1.0 → t_sql-4.2.0}/PKG-INFO +1 -1
  2. {t_sql-4.1.0 → t_sql-4.2.0}/pyproject.toml +1 -1
  3. {t_sql-4.1.0 → t_sql-4.2.0}/tsql/query_builder.py +48 -18
  4. {t_sql-4.1.0 → t_sql-4.2.0}/.dockerignore +0 -0
  5. {t_sql-4.1.0 → t_sql-4.2.0}/.github/workflows/publish.yml +0 -0
  6. {t_sql-4.1.0 → t_sql-4.2.0}/.github/workflows/test.yml +0 -0
  7. {t_sql-4.1.0 → t_sql-4.2.0}/.gitignore +0 -0
  8. {t_sql-4.1.0 → t_sql-4.2.0}/Dockerfile +0 -0
  9. {t_sql-4.1.0 → t_sql-4.2.0}/LICENSE +0 -0
  10. {t_sql-4.1.0 → t_sql-4.2.0}/README.md +0 -0
  11. {t_sql-4.1.0 → t_sql-4.2.0}/compose.yaml +0 -0
  12. {t_sql-4.1.0 → t_sql-4.2.0}/context7.json +0 -0
  13. {t_sql-4.1.0 → t_sql-4.2.0}/pytest.ini +0 -0
  14. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_alembic_integration.py +0 -0
  15. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_asyncpg_integration.py +0 -0
  16. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_different_object_types.py +0 -0
  17. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_escaped.py +0 -0
  18. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_escaped_binary_hex.py +0 -0
  19. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_helper_functions.py +0 -0
  20. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_injection_edge_cases.py +0 -0
  21. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_injection_protection_validation.py +0 -0
  22. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_injections_for_escaped.py +0 -0
  23. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_mysql_integration.py +0 -0
  24. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_parameter_names.py +0 -0
  25. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_query_builder.py +0 -0
  26. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_sqlalchemy_integration.py +0 -0
  27. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_sqlite_integration.py +0 -0
  28. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_styles.py +0 -0
  29. {t_sql-4.1.0 → t_sql-4.2.0}/tests/test_tsql.py +0 -0
  30. {t_sql-4.1.0 → t_sql-4.2.0}/tsql/__init__.py +0 -0
  31. {t_sql-4.1.0 → t_sql-4.2.0}/tsql/styles.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: t-sql
3
- Version: 4.1.0
3
+ Version: 4.2.0
4
4
  Summary: Safe SQL. SQL queries for python t-strings (PEP 750)
5
5
  Project-URL: Homepage, https://github.com/nhumrich/t-sql
6
6
  License-File: LICENSE
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "t-sql"
7
- version = "4.1.0"
7
+ version = "4.2.0"
8
8
  description = "Safe SQL. SQL queries for python t-strings (PEP 750)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.14"
@@ -240,7 +240,7 @@ class Table:
240
240
  continue
241
241
  field_value = getattr(cls, field_name, None)
242
242
 
243
- # Check for Ellipsis syntax: id = ...
243
+ # Check for Ellipsis syntax: id = ...~
244
244
  if field_value is ...:
245
245
  if field_name not in all_fields:
246
246
  all_fields[field_name] = {
@@ -452,7 +452,7 @@ class Condition:
452
452
  class Join:
453
453
  """Represents a JOIN clause"""
454
454
 
455
- def __init__(self, table: 'Table', condition: Condition, join_type: str = 'INNER'):
455
+ def __init__(self, table: type['Table'], condition: Condition, join_type: str = 'INNER'):
456
456
  self.table = table
457
457
  self.condition = condition
458
458
  self.join_type = join_type
@@ -495,7 +495,7 @@ class QueryBuilder(ABC):
495
495
  class InsertBuilder(QueryBuilder):
496
496
  """Fluent interface for building INSERT queries"""
497
497
 
498
- def __init__(self, base_table: 'Table', values: dict[str, Any]):
498
+ def __init__(self, base_table: type['Table'], values: dict[str, Any]):
499
499
  self.base_table = base_table
500
500
 
501
501
  # Apply defaults from SQLAlchemy columns if available
@@ -563,13 +563,23 @@ class InsertBuilder(QueryBuilder):
563
563
  self._update_cols = update
564
564
  return self
565
565
 
566
- def returning(self, *columns: str) -> 'InsertBuilder':
566
+ def returning(self, *columns: Union[str, Column]) -> 'InsertBuilder':
567
567
  """Add RETURNING clause (Postgres/SQLite only)
568
568
 
569
569
  Args:
570
- columns: Column names to return, or none for RETURNING *
570
+ columns: Column names (strings) or Column objects to return, or none for RETURNING *
571
571
  """
572
- self._returning_cols = list(columns) if columns else ['*']
572
+ if columns:
573
+ # Convert Column objects to their column names
574
+ col_names = []
575
+ for col in columns:
576
+ if isinstance(col, Column):
577
+ col_names.append(col.column_name)
578
+ else:
579
+ col_names.append(col)
580
+ self._returning_cols = col_names
581
+ else:
582
+ self._returning_cols = ['*']
573
583
  return self
574
584
 
575
585
  def to_tsql(self) -> TSQL:
@@ -677,7 +687,7 @@ class InsertBuilder(QueryBuilder):
677
687
  class UpdateBuilder(QueryBuilder):
678
688
  """Fluent interface for building UPDATE queries"""
679
689
 
680
- def __init__(self, base_table: 'Table', values: dict[str, Any]):
690
+ def __init__(self, base_table: type['Table'], values: dict[str, Any]):
681
691
  self.base_table = base_table
682
692
 
683
693
  # Apply onupdate defaults from SQLAlchemy columns if available
@@ -726,13 +736,23 @@ class UpdateBuilder(QueryBuilder):
726
736
  self._requires_where = False
727
737
  return self
728
738
 
729
- def returning(self, *columns: str) -> 'UpdateBuilder':
739
+ def returning(self, *columns: Union[str, Column]) -> 'UpdateBuilder':
730
740
  """Add RETURNING clause (Postgres/SQLite only)
731
741
 
732
742
  Args:
733
- columns: Column names to return, or none for RETURNING *
743
+ columns: Column names (strings) or Column objects to return, or none for RETURNING *
734
744
  """
735
- self._returning_cols = list(columns) if columns else ['*']
745
+ if columns:
746
+ # Convert Column objects to their column names
747
+ col_names = []
748
+ for col in columns:
749
+ if isinstance(col, Column):
750
+ col_names.append(col.column_name)
751
+ else:
752
+ col_names.append(col)
753
+ self._returning_cols = col_names
754
+ else:
755
+ self._returning_cols = ['*']
736
756
  return self
737
757
 
738
758
  def to_tsql(self) -> TSQL:
@@ -790,7 +810,7 @@ class UpdateBuilder(QueryBuilder):
790
810
  class DeleteBuilder(QueryBuilder):
791
811
  """Fluent interface for building DELETE queries"""
792
812
 
793
- def __init__(self, base_table: 'Table'):
813
+ def __init__(self, base_table: type['Table']):
794
814
  self.base_table = base_table
795
815
  self._conditions: List[Union[Condition, Template]] = []
796
816
  self._returning_cols: Optional[List[str]] = None
@@ -817,13 +837,23 @@ class DeleteBuilder(QueryBuilder):
817
837
  self._requires_where = False
818
838
  return self
819
839
 
820
- def returning(self, *columns: str) -> 'DeleteBuilder':
840
+ def returning(self, *columns: Union[str, Column]) -> 'DeleteBuilder':
821
841
  """Add RETURNING clause (Postgres/SQLite only)
822
842
 
823
843
  Args:
824
- columns: Column names to return, or none for RETURNING *
844
+ columns: Column names (strings) or Column objects to return, or none for RETURNING *
825
845
  """
826
- self._returning_cols = list(columns) if columns else ['*']
846
+ if columns:
847
+ # Convert Column objects to their column names
848
+ col_names = []
849
+ for col in columns:
850
+ if isinstance(col, Column):
851
+ col_names.append(col.column_name)
852
+ else:
853
+ col_names.append(col)
854
+ self._returning_cols = col_names
855
+ else:
856
+ self._returning_cols = ['*']
827
857
  return self
828
858
 
829
859
  def to_tsql(self) -> TSQL:
@@ -880,7 +910,7 @@ class DeleteBuilder(QueryBuilder):
880
910
  class SelectQueryBuilder(QueryBuilder):
881
911
  """Fluent interface for building SQL SELECT queries"""
882
912
 
883
- def __init__(self, base_table: 'Table'):
913
+ def __init__(self, base_table: type['Table']):
884
914
  self.base_table = base_table
885
915
  self._columns: Optional[List[Column]] = None
886
916
  self._conditions: List[Condition] = []
@@ -918,16 +948,16 @@ class SelectQueryBuilder(QueryBuilder):
918
948
  self._conditions.append(condition)
919
949
  return self
920
950
 
921
- def join(self, table: 'Table', on: Condition, join_type: str = 'INNER') -> 'SelectQueryBuilder':
951
+ def join(self, table: type['Table'], on: Condition, join_type: str = 'INNER') -> 'SelectQueryBuilder':
922
952
  """Add a JOIN clause"""
923
953
  self._joins.append(Join(table, on, join_type))
924
954
  return self
925
955
 
926
- def left_join(self, table: 'Table', on: Condition) -> 'SelectQueryBuilder':
956
+ def left_join(self, table: type['Table'], on: Condition) -> 'SelectQueryBuilder':
927
957
  """Add a LEFT JOIN clause"""
928
958
  return self.join(table, on, 'LEFT')
929
959
 
930
- def right_join(self, table: 'Table', on: Condition) -> 'SelectQueryBuilder':
960
+ def right_join(self, table: type['Table'], on: Condition) -> 'SelectQueryBuilder':
931
961
  """Add a RIGHT JOIN clause"""
932
962
  return self.join(table, on, 'RIGHT')
933
963
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes