t-sql 4.9.2__tar.gz → 4.9.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 (39) hide show
  1. {t_sql-4.9.2 → t_sql-4.9.3}/PKG-INFO +1 -1
  2. {t_sql-4.9.2 → t_sql-4.9.3}/pyproject.toml +1 -1
  3. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_escaped.py +2 -2
  4. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_tsql.py +30 -0
  5. {t_sql-4.9.2 → t_sql-4.9.3}/tsql/__init__.py +3 -3
  6. {t_sql-4.9.2 → t_sql-4.9.3}/.dockerignore +0 -0
  7. {t_sql-4.9.2 → t_sql-4.9.3}/.github/workflows/publish.yml +0 -0
  8. {t_sql-4.9.2 → t_sql-4.9.3}/.github/workflows/test.yml +0 -0
  9. {t_sql-4.9.2 → t_sql-4.9.3}/.gitignore +0 -0
  10. {t_sql-4.9.2 → t_sql-4.9.3}/Dockerfile +0 -0
  11. {t_sql-4.9.2 → t_sql-4.9.3}/LICENSE +0 -0
  12. {t_sql-4.9.2 → t_sql-4.9.3}/README.md +0 -0
  13. {t_sql-4.9.2 → t_sql-4.9.3}/compose.yaml +0 -0
  14. {t_sql-4.9.2 → t_sql-4.9.3}/context7.json +0 -0
  15. {t_sql-4.9.2 → t_sql-4.9.3}/pytest.ini +0 -0
  16. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_alembic_integration.py +0 -0
  17. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_asyncpg_integration.py +0 -0
  18. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_deep_nesting.py +0 -0
  19. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_different_object_types.py +0 -0
  20. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_error_messages.py +0 -0
  21. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_escaped_binary_hex.py +0 -0
  22. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_helper_functions.py +0 -0
  23. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_injection_edge_cases.py +0 -0
  24. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_injection_protection_validation.py +0 -0
  25. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_injections_for_escaped.py +0 -0
  26. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_like_patterns.py +0 -0
  27. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_mysql_integration.py +0 -0
  28. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_parameter_names.py +0 -0
  29. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_query_builder.py +0 -0
  30. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_sqlalchemy_integration.py +0 -0
  31. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_sqlite_integration.py +0 -0
  32. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_string_based_builders.py +0 -0
  33. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_styles.py +0 -0
  34. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_template_in_builders.py +0 -0
  35. {t_sql-4.9.2 → t_sql-4.9.3}/tests/test_type_processor.py +0 -0
  36. {t_sql-4.9.2 → t_sql-4.9.3}/tsql/query_builder.py +0 -0
  37. {t_sql-4.9.2 → t_sql-4.9.3}/tsql/row.py +0 -0
  38. {t_sql-4.9.2 → t_sql-4.9.3}/tsql/styles.py +0 -0
  39. {t_sql-4.9.2 → t_sql-4.9.3}/tsql/type_processor.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: t-sql
3
- Version: 4.9.2
3
+ Version: 4.9.3
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.9.2"
7
+ version = "4.9.3"
8
8
  description = "Safe SQL. SQL queries for python t-strings (PEP 750)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.14"
@@ -123,8 +123,8 @@ def test_escaped_handles_float_values():
123
123
  """Test proper escaping of float values"""
124
124
  price = 19.99
125
125
  result = tsql.render(t"SELECT * FROM products WHERE price = {price}", style=tsql.styles.ESCAPED)
126
- # Note: floats get converted to strings by the formatter before reaching ESCAPED style
127
- assert result[0] == "SELECT * FROM products WHERE price = '19.99'"
126
+ # Floats are passed through and rendered as numeric (no quotes) - correct SQL behavior
127
+ assert result[0] == "SELECT * FROM products WHERE price = 19.99"
128
128
  assert result[1] == []
129
129
 
130
130
 
@@ -218,4 +218,34 @@ def test_empty_collections_preserved():
218
218
  assert isinstance(r3.values[0], set)
219
219
 
220
220
 
221
+ def test_custom_object_preserved():
222
+ """Custom objects should pass through for database drivers with custom codecs."""
223
+ class Point:
224
+ def __init__(self, x, y):
225
+ self.x = x
226
+ self.y = y
227
+
228
+ p = Point(3, 4)
229
+ result = tsql.render(t'INSERT INTO coords (loc) VALUES ({p})')
230
+ assert result.sql == 'INSERT INTO coords (loc) VALUES (?)'
231
+ assert isinstance(result.values[0], Point)
232
+ assert result.values[0].x == 3
233
+ assert result.values[0].y == 4
234
+
235
+
236
+ def test_custom_object_with_format_spec_stringifies():
237
+ """Custom objects WITH a format spec should be formatted (stringified)."""
238
+ class Point:
239
+ def __init__(self, x, y):
240
+ self.x = x
241
+ self.y = y
242
+ def __format__(self, spec):
243
+ return f"POINT({self.x},{self.y})"
244
+
245
+ p = Point(3, 4)
246
+ result = tsql.render(t'INSERT INTO coords (loc) VALUES ({p:s})')
247
+ assert result.values[0] == "POINT(3,4)"
248
+ assert isinstance(result.values[0], str)
249
+
250
+
221
251
 
@@ -193,11 +193,11 @@ class TSQL:
193
193
  return [Parameter(val.expression, value)]
194
194
  case _, int():
195
195
  return [Parameter(val.expression, val.value)]
196
- case '', datetime.datetime() | datetime.date() | datetime.time() | datetime.timedelta():
197
- return [Parameter(val.expression, value)]
198
- case '', dict() | list() | set():
196
+ case '', _:
197
+ # No format spec - pass through value as-is for database driver to handle
199
198
  return [Parameter(val.expression, value)]
200
199
  case _, _:
200
+ # Has format spec - apply formatting (e.g., {dt:%Y-%m-%d})
201
201
  return [Parameter(val.expression, formatter.format_field(value, val.format_spec))]
202
202
 
203
203
  if isinstance(val, Template):
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
File without changes
File without changes