t-sql 0.1.1__tar.gz → 0.1.2__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.
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025
3
+ Copyright (c) 2025 Nick Humrich
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.
t_sql-0.1.2/PKG-INFO ADDED
@@ -0,0 +1,160 @@
1
+ Metadata-Version: 2.4
2
+ Name: t-sql
3
+ Version: 0.1.2
4
+ Summary: Safe SQL. SQL queries for python t-strings (PEP 750)
5
+ Requires-Python: >=3.14
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Dynamic: license-file
9
+
10
+ # tsql
11
+
12
+ A lightweight SQL templating library that leverages Python 3.14's t-strings (PEP 750).
13
+
14
+ TSQL provides a safe way to write SQL queries using Python's template strings (t-strings) while preventing SQL injection attacks through multiple parameter styling options.
15
+
16
+ ## ⚠️ Python Version Requirement
17
+ This library requires Python 3.14b1 or newer.
18
+
19
+ TSQL is built specifically to take advantage of the new t-string feature introduced in PEP 750, which is only available in Python 3.14+.
20
+
21
+
22
+ ## Parameter Styles
23
+
24
+ - **QMARK** (default): Uses `?` placeholders
25
+ - **NUMERIC**: Uses `:1`, `:2`, etc. placeholders
26
+ - **NAMED**: Uses `:name` placeholders
27
+ - **FORMAT**: Uses `%s` placeholders
28
+ - **PYFORMAT**: Uses `%(name)s` placeholders
29
+ - **NUMERIC_DOLLAR**: Uses `$1`, `$2`, etc. (PostgreSQL native)
30
+ - **ESCAPED**: Escapes values directly into SQL (no parameters)
31
+
32
+ ## Examples:
33
+
34
+ ```python
35
+
36
+ # Basic usage with different parameter styles
37
+ import tsql
38
+ import tsql.styles
39
+
40
+ name = 'billy'
41
+ query = t'select * from users where name={name}'
42
+
43
+ # Default QMARK style
44
+ print(tsql.render(query))
45
+ # ('select * from users where name = ?', ['billy'])
46
+
47
+ # PostgreSQL native style
48
+ print(tsql.render(query, style=tsql.styles.NUMERIC_DOLLAR))
49
+ # ('select * from users where name = $1', ['billy'])
50
+
51
+ # ESCAPED style (no parameters)
52
+ print(tsql.render(query, style=tsql.styles.ESCAPED))
53
+ # ("select * from users where name = 'billy'", [])
54
+
55
+ # SQL injection prevention
56
+ name = "billy ' and 1=1 --"
57
+ print(tsql.render(query, style=tsql.styles.ESCAPED))
58
+ # ("select * from users where name = 'billy '' and 1=1 --'", [])
59
+
60
+ ```
61
+
62
+ ## Format-spec helpers
63
+
64
+ There are some built-in format spec helpers that can change the way some
65
+ parts of the library work.
66
+
67
+ ### Literal
68
+ One common example is you may want to set the name
69
+ of a column dynamically. By using the `literal` format spec, the value will
70
+ be sanitized against a valid literal and put straight into the sql query since
71
+ you cannot parameterize that part of a query, example:
72
+
73
+ ```python
74
+ query = t'select * from {table:literal} where {col:literal}={val}'
75
+ ```
76
+
77
+ or, a full example:
78
+ ```python
79
+
80
+ # with a like clause
81
+ min_age = 30
82
+ search_column = "name"
83
+ pattern = "O'Brien"
84
+ is_active = True
85
+ tsql.render(t"SELECT * FROM test_users WHERE age >= {min_age} AND {search_column:literal} LIKE '%' || {pattern} || '%' AND active = {is_active}")
86
+ ```
87
+
88
+ ### unsafe
89
+ You may want to do advanced things that may otherwise be considered unsfe.
90
+ This is okay if you can be sure that a user is not providing input. Like maybe
91
+ you care storing a query for some reason.
92
+ As per the name, this can open you up to sql injection and should be used with
93
+ extreme caution.
94
+ You can use the "unsafe" format spec for these
95
+ cases:
96
+ ```python
97
+ dynamic_where = input('type where clause')
98
+ tsql.render(f"SELECT * FROM users WHERE {dynamic_where:unsafe}")
99
+ ```
100
+
101
+ ### as_values
102
+
103
+ The spec `:as_values` formats a dictionary into the format:
104
+ `(key1, key2, ...) VALUES (value1, value2, ...)` for uses in insert statements.
105
+
106
+ ### traditional format_spec
107
+
108
+ All other format specs should be handled as they would in a normal f-string.
109
+
110
+ ## Included helper methods
111
+
112
+ ```python
113
+ # select
114
+ tsql.select('table', 'abc123')
115
+ # SELECT * FROM table WHERE id='abc123'
116
+
117
+ # select with multiple ids and specific columns
118
+ tsql.select('users', ['abc123', 'def456'], columns=['name', 'age'])
119
+ # SELECT name, age FROM users WHERE id in ('abc123', 'def456')
120
+
121
+
122
+ # t_join (joins multiple t-strings together like .join on a str)
123
+ tsql.t_join(t" ", [t"hello", t"there"])
124
+ # t"hello there"
125
+
126
+
127
+ # insert
128
+ table = 'users'
129
+ values = {'id': 'abc123', 'name': 'bob', 'email': 'bob@example.com'}
130
+ tsql.insert(table, values)
131
+ # INSERT INTO users (id, name, email) VALUES ('abc123', 'bob', 'bob@example.com')
132
+
133
+ # update values on a single row
134
+ table = 'users'
135
+ values = {'name': 'joe', 'email': 'joe@example.com'}
136
+ tsql.update(table, values, id='abc123')
137
+ # UPDATE users SET name='joe', email='joe@example.com' WHERE id='abc123'
138
+ ```
139
+
140
+ # Note on usage
141
+
142
+ This library should ideally be used inside middleware or library code
143
+ right before making an actual query. It can be used to enforce
144
+ using t-strings and prevent using raw strings.
145
+
146
+ For example:
147
+
148
+ ```
149
+ from string.templatelib import Template
150
+
151
+ import tsql
152
+
153
+ def execute_sql_query(query):
154
+ if not isinstance(query, Template):
155
+ raise TypeError('Cannot make a query without using t-strings')
156
+
157
+
158
+ return sql_engine.execute(*tsql.render(query))
159
+
160
+ ```
t_sql-0.1.2/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # tsql
2
+
3
+ A lightweight SQL templating library that leverages Python 3.14's t-strings (PEP 750).
4
+
5
+ TSQL provides a safe way to write SQL queries using Python's template strings (t-strings) while preventing SQL injection attacks through multiple parameter styling options.
6
+
7
+ ## ⚠️ Python Version Requirement
8
+ This library requires Python 3.14b1 or newer.
9
+
10
+ TSQL is built specifically to take advantage of the new t-string feature introduced in PEP 750, which is only available in Python 3.14+.
11
+
12
+
13
+ ## Parameter Styles
14
+
15
+ - **QMARK** (default): Uses `?` placeholders
16
+ - **NUMERIC**: Uses `:1`, `:2`, etc. placeholders
17
+ - **NAMED**: Uses `:name` placeholders
18
+ - **FORMAT**: Uses `%s` placeholders
19
+ - **PYFORMAT**: Uses `%(name)s` placeholders
20
+ - **NUMERIC_DOLLAR**: Uses `$1`, `$2`, etc. (PostgreSQL native)
21
+ - **ESCAPED**: Escapes values directly into SQL (no parameters)
22
+
23
+ ## Examples:
24
+
25
+ ```python
26
+
27
+ # Basic usage with different parameter styles
28
+ import tsql
29
+ import tsql.styles
30
+
31
+ name = 'billy'
32
+ query = t'select * from users where name={name}'
33
+
34
+ # Default QMARK style
35
+ print(tsql.render(query))
36
+ # ('select * from users where name = ?', ['billy'])
37
+
38
+ # PostgreSQL native style
39
+ print(tsql.render(query, style=tsql.styles.NUMERIC_DOLLAR))
40
+ # ('select * from users where name = $1', ['billy'])
41
+
42
+ # ESCAPED style (no parameters)
43
+ print(tsql.render(query, style=tsql.styles.ESCAPED))
44
+ # ("select * from users where name = 'billy'", [])
45
+
46
+ # SQL injection prevention
47
+ name = "billy ' and 1=1 --"
48
+ print(tsql.render(query, style=tsql.styles.ESCAPED))
49
+ # ("select * from users where name = 'billy '' and 1=1 --'", [])
50
+
51
+ ```
52
+
53
+ ## Format-spec helpers
54
+
55
+ There are some built-in format spec helpers that can change the way some
56
+ parts of the library work.
57
+
58
+ ### Literal
59
+ One common example is you may want to set the name
60
+ of a column dynamically. By using the `literal` format spec, the value will
61
+ be sanitized against a valid literal and put straight into the sql query since
62
+ you cannot parameterize that part of a query, example:
63
+
64
+ ```python
65
+ query = t'select * from {table:literal} where {col:literal}={val}'
66
+ ```
67
+
68
+ or, a full example:
69
+ ```python
70
+
71
+ # with a like clause
72
+ min_age = 30
73
+ search_column = "name"
74
+ pattern = "O'Brien"
75
+ is_active = True
76
+ tsql.render(t"SELECT * FROM test_users WHERE age >= {min_age} AND {search_column:literal} LIKE '%' || {pattern} || '%' AND active = {is_active}")
77
+ ```
78
+
79
+ ### unsafe
80
+ You may want to do advanced things that may otherwise be considered unsfe.
81
+ This is okay if you can be sure that a user is not providing input. Like maybe
82
+ you care storing a query for some reason.
83
+ As per the name, this can open you up to sql injection and should be used with
84
+ extreme caution.
85
+ You can use the "unsafe" format spec for these
86
+ cases:
87
+ ```python
88
+ dynamic_where = input('type where clause')
89
+ tsql.render(f"SELECT * FROM users WHERE {dynamic_where:unsafe}")
90
+ ```
91
+
92
+ ### as_values
93
+
94
+ The spec `:as_values` formats a dictionary into the format:
95
+ `(key1, key2, ...) VALUES (value1, value2, ...)` for uses in insert statements.
96
+
97
+ ### traditional format_spec
98
+
99
+ All other format specs should be handled as they would in a normal f-string.
100
+
101
+ ## Included helper methods
102
+
103
+ ```python
104
+ # select
105
+ tsql.select('table', 'abc123')
106
+ # SELECT * FROM table WHERE id='abc123'
107
+
108
+ # select with multiple ids and specific columns
109
+ tsql.select('users', ['abc123', 'def456'], columns=['name', 'age'])
110
+ # SELECT name, age FROM users WHERE id in ('abc123', 'def456')
111
+
112
+
113
+ # t_join (joins multiple t-strings together like .join on a str)
114
+ tsql.t_join(t" ", [t"hello", t"there"])
115
+ # t"hello there"
116
+
117
+
118
+ # insert
119
+ table = 'users'
120
+ values = {'id': 'abc123', 'name': 'bob', 'email': 'bob@example.com'}
121
+ tsql.insert(table, values)
122
+ # INSERT INTO users (id, name, email) VALUES ('abc123', 'bob', 'bob@example.com')
123
+
124
+ # update values on a single row
125
+ table = 'users'
126
+ values = {'name': 'joe', 'email': 'joe@example.com'}
127
+ tsql.update(table, values, id='abc123')
128
+ # UPDATE users SET name='joe', email='joe@example.com' WHERE id='abc123'
129
+ ```
130
+
131
+ # Note on usage
132
+
133
+ This library should ideally be used inside middleware or library code
134
+ right before making an actual query. It can be used to enforce
135
+ using t-strings and prevent using raw strings.
136
+
137
+ For example:
138
+
139
+ ```
140
+ from string.templatelib import Template
141
+
142
+ import tsql
143
+
144
+ def execute_sql_query(query):
145
+ if not isinstance(query, Template):
146
+ raise TypeError('Cannot make a query without using t-strings')
147
+
148
+
149
+ return sql_engine.execute(*tsql.render(query))
150
+
151
+ ```
@@ -0,0 +1,15 @@
1
+ [project]
2
+ name = "t-sql"
3
+ version = "0.1.2"
4
+ description = "Safe SQL. SQL queries for python t-strings (PEP 750)"
5
+ readme = "README.md"
6
+ requires-python = ">=3.14"
7
+ dependencies = []
8
+
9
+ [dependency-groups]
10
+ dev = [
11
+ "anyio>=4.9.0",
12
+ "asyncpg>=0.30.0",
13
+ "pytest>=8.3.5",
14
+ "pytest-asyncio>=0.24.0",
15
+ ]
@@ -0,0 +1,160 @@
1
+ Metadata-Version: 2.4
2
+ Name: t-sql
3
+ Version: 0.1.2
4
+ Summary: Safe SQL. SQL queries for python t-strings (PEP 750)
5
+ Requires-Python: >=3.14
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Dynamic: license-file
9
+
10
+ # tsql
11
+
12
+ A lightweight SQL templating library that leverages Python 3.14's t-strings (PEP 750).
13
+
14
+ TSQL provides a safe way to write SQL queries using Python's template strings (t-strings) while preventing SQL injection attacks through multiple parameter styling options.
15
+
16
+ ## ⚠️ Python Version Requirement
17
+ This library requires Python 3.14b1 or newer.
18
+
19
+ TSQL is built specifically to take advantage of the new t-string feature introduced in PEP 750, which is only available in Python 3.14+.
20
+
21
+
22
+ ## Parameter Styles
23
+
24
+ - **QMARK** (default): Uses `?` placeholders
25
+ - **NUMERIC**: Uses `:1`, `:2`, etc. placeholders
26
+ - **NAMED**: Uses `:name` placeholders
27
+ - **FORMAT**: Uses `%s` placeholders
28
+ - **PYFORMAT**: Uses `%(name)s` placeholders
29
+ - **NUMERIC_DOLLAR**: Uses `$1`, `$2`, etc. (PostgreSQL native)
30
+ - **ESCAPED**: Escapes values directly into SQL (no parameters)
31
+
32
+ ## Examples:
33
+
34
+ ```python
35
+
36
+ # Basic usage with different parameter styles
37
+ import tsql
38
+ import tsql.styles
39
+
40
+ name = 'billy'
41
+ query = t'select * from users where name={name}'
42
+
43
+ # Default QMARK style
44
+ print(tsql.render(query))
45
+ # ('select * from users where name = ?', ['billy'])
46
+
47
+ # PostgreSQL native style
48
+ print(tsql.render(query, style=tsql.styles.NUMERIC_DOLLAR))
49
+ # ('select * from users where name = $1', ['billy'])
50
+
51
+ # ESCAPED style (no parameters)
52
+ print(tsql.render(query, style=tsql.styles.ESCAPED))
53
+ # ("select * from users where name = 'billy'", [])
54
+
55
+ # SQL injection prevention
56
+ name = "billy ' and 1=1 --"
57
+ print(tsql.render(query, style=tsql.styles.ESCAPED))
58
+ # ("select * from users where name = 'billy '' and 1=1 --'", [])
59
+
60
+ ```
61
+
62
+ ## Format-spec helpers
63
+
64
+ There are some built-in format spec helpers that can change the way some
65
+ parts of the library work.
66
+
67
+ ### Literal
68
+ One common example is you may want to set the name
69
+ of a column dynamically. By using the `literal` format spec, the value will
70
+ be sanitized against a valid literal and put straight into the sql query since
71
+ you cannot parameterize that part of a query, example:
72
+
73
+ ```python
74
+ query = t'select * from {table:literal} where {col:literal}={val}'
75
+ ```
76
+
77
+ or, a full example:
78
+ ```python
79
+
80
+ # with a like clause
81
+ min_age = 30
82
+ search_column = "name"
83
+ pattern = "O'Brien"
84
+ is_active = True
85
+ tsql.render(t"SELECT * FROM test_users WHERE age >= {min_age} AND {search_column:literal} LIKE '%' || {pattern} || '%' AND active = {is_active}")
86
+ ```
87
+
88
+ ### unsafe
89
+ You may want to do advanced things that may otherwise be considered unsfe.
90
+ This is okay if you can be sure that a user is not providing input. Like maybe
91
+ you care storing a query for some reason.
92
+ As per the name, this can open you up to sql injection and should be used with
93
+ extreme caution.
94
+ You can use the "unsafe" format spec for these
95
+ cases:
96
+ ```python
97
+ dynamic_where = input('type where clause')
98
+ tsql.render(f"SELECT * FROM users WHERE {dynamic_where:unsafe}")
99
+ ```
100
+
101
+ ### as_values
102
+
103
+ The spec `:as_values` formats a dictionary into the format:
104
+ `(key1, key2, ...) VALUES (value1, value2, ...)` for uses in insert statements.
105
+
106
+ ### traditional format_spec
107
+
108
+ All other format specs should be handled as they would in a normal f-string.
109
+
110
+ ## Included helper methods
111
+
112
+ ```python
113
+ # select
114
+ tsql.select('table', 'abc123')
115
+ # SELECT * FROM table WHERE id='abc123'
116
+
117
+ # select with multiple ids and specific columns
118
+ tsql.select('users', ['abc123', 'def456'], columns=['name', 'age'])
119
+ # SELECT name, age FROM users WHERE id in ('abc123', 'def456')
120
+
121
+
122
+ # t_join (joins multiple t-strings together like .join on a str)
123
+ tsql.t_join(t" ", [t"hello", t"there"])
124
+ # t"hello there"
125
+
126
+
127
+ # insert
128
+ table = 'users'
129
+ values = {'id': 'abc123', 'name': 'bob', 'email': 'bob@example.com'}
130
+ tsql.insert(table, values)
131
+ # INSERT INTO users (id, name, email) VALUES ('abc123', 'bob', 'bob@example.com')
132
+
133
+ # update values on a single row
134
+ table = 'users'
135
+ values = {'name': 'joe', 'email': 'joe@example.com'}
136
+ tsql.update(table, values, id='abc123')
137
+ # UPDATE users SET name='joe', email='joe@example.com' WHERE id='abc123'
138
+ ```
139
+
140
+ # Note on usage
141
+
142
+ This library should ideally be used inside middleware or library code
143
+ right before making an actual query. It can be used to enforce
144
+ using t-strings and prevent using raw strings.
145
+
146
+ For example:
147
+
148
+ ```
149
+ from string.templatelib import Template
150
+
151
+ import tsql
152
+
153
+ def execute_sql_query(query):
154
+ if not isinstance(query, Template):
155
+ raise TypeError('Cannot make a query without using t-strings')
156
+
157
+
158
+ return sql_engine.execute(*tsql.render(query))
159
+
160
+ ```
@@ -4,8 +4,12 @@ pyproject.toml
4
4
  t_sql.egg-info/PKG-INFO
5
5
  t_sql.egg-info/SOURCES.txt
6
6
  t_sql.egg-info/dependency_links.txt
7
- t_sql.egg-info/requires.txt
8
7
  t_sql.egg-info/top_level.txt
8
+ tests/test_asyncpg_integration.py
9
+ tests/test_different_object_types.py
10
+ tests/test_escaped.py
11
+ tests/test_helper_functions.py
12
+ tests/test_styles.py
9
13
  tests/test_tsql.py
10
14
  tsql/__init__.py
11
- tsql/tsql.py
15
+ tsql/styles.py