databasesupasafe 1.0.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.
- databasesupasafe-1.0.0/PKG-INFO +251 -0
- databasesupasafe-1.0.0/README.md +204 -0
- databasesupasafe-1.0.0/databasesupasafe.egg-info/PKG-INFO +251 -0
- databasesupasafe-1.0.0/databasesupasafe.egg-info/SOURCES.txt +14 -0
- databasesupasafe-1.0.0/databasesupasafe.egg-info/dependency_links.txt +1 -0
- databasesupasafe-1.0.0/databasesupasafe.egg-info/not-zip-safe +1 -0
- databasesupasafe-1.0.0/databasesupasafe.egg-info/requires.txt +18 -0
- databasesupasafe-1.0.0/databasesupasafe.egg-info/top_level.txt +1 -0
- databasesupasafe-1.0.0/dbhandler/__init__.py +26 -0
- databasesupasafe-1.0.0/dbhandler/core.py +486 -0
- databasesupasafe-1.0.0/dbhandler/exceptions.py +23 -0
- databasesupasafe-1.0.0/dbhandler/models.py +285 -0
- databasesupasafe-1.0.0/dbhandler/query.py +216 -0
- databasesupasafe-1.0.0/setup.cfg +4 -0
- databasesupasafe-1.0.0/setup.py +107 -0
- databasesupasafe-1.0.0/tests/test_dbhandler.py +300 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: databasesupasafe
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A lightweight Python package for managing SQLite, PostgreSQL, and MySQL databases.
|
|
5
|
+
Home-page: https://github.com/yourname/dbhandler
|
|
6
|
+
Author: dbhandler contributors
|
|
7
|
+
Author-email: you@example.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: Topic :: Database
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: >=3.8
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: api-feature
|
|
23
|
+
Provides-Extra: postgresql
|
|
24
|
+
Requires-Dist: psycopg2-binary>=2.9; extra == "postgresql"
|
|
25
|
+
Provides-Extra: mysql
|
|
26
|
+
Requires-Dist: mysql-connector-python>=8.0; extra == "mysql"
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: psycopg2-binary>=2.9; extra == "all"
|
|
29
|
+
Requires-Dist: mysql-connector-python>=8.0; extra == "all"
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
33
|
+
Requires-Dist: black; extra == "dev"
|
|
34
|
+
Requires-Dist: isort; extra == "dev"
|
|
35
|
+
Requires-Dist: mypy; extra == "dev"
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: author-email
|
|
38
|
+
Dynamic: classifier
|
|
39
|
+
Dynamic: description
|
|
40
|
+
Dynamic: description-content-type
|
|
41
|
+
Dynamic: home-page
|
|
42
|
+
Dynamic: license
|
|
43
|
+
Dynamic: provides-extra
|
|
44
|
+
Dynamic: requires-dist
|
|
45
|
+
Dynamic: requires-python
|
|
46
|
+
Dynamic: summary
|
|
47
|
+
|
|
48
|
+
# dbhandler
|
|
49
|
+
|
|
50
|
+
A lightweight Python package for managing **SQLite**, **PostgreSQL**, and **MySQL** databases — with a fluent query builder and an ORM-style model layer.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# SQLite only (no extra dependencies)
|
|
58
|
+
pip install .
|
|
59
|
+
|
|
60
|
+
# With PostgreSQL support
|
|
61
|
+
pip install ".[postgresql]"
|
|
62
|
+
|
|
63
|
+
# With MySQL support
|
|
64
|
+
pip install ".[mysql]"
|
|
65
|
+
|
|
66
|
+
# Everything
|
|
67
|
+
pip install ".[all]"
|
|
68
|
+
|
|
69
|
+
# Development tools
|
|
70
|
+
pip install ".[dev]"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Quick Start
|
|
76
|
+
|
|
77
|
+
### DBHandler — direct SQL
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from dbhandler import DBHandler
|
|
81
|
+
|
|
82
|
+
# SQLite (in-memory)
|
|
83
|
+
with DBHandler("sqlite", database=":memory:") as db:
|
|
84
|
+
db.execute("""
|
|
85
|
+
CREATE TABLE users (
|
|
86
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
87
|
+
name TEXT NOT NULL,
|
|
88
|
+
email TEXT NOT NULL UNIQUE,
|
|
89
|
+
age INTEGER DEFAULT 0
|
|
90
|
+
)
|
|
91
|
+
""")
|
|
92
|
+
|
|
93
|
+
# Insert a single row
|
|
94
|
+
db.insert("users", {"name": "Alice", "email": "alice@example.com", "age": 30})
|
|
95
|
+
|
|
96
|
+
# Insert many rows
|
|
97
|
+
db.insert_many("users", [
|
|
98
|
+
{"name": "Bob", "email": "bob@example.com", "age": 25},
|
|
99
|
+
{"name": "Carol", "email": "carol@example.com", "age": 35},
|
|
100
|
+
])
|
|
101
|
+
|
|
102
|
+
# Select with a WHERE clause
|
|
103
|
+
adults = db.select("users", where="age >= ?", params=(30,), order_by="name ASC")
|
|
104
|
+
for user in adults:
|
|
105
|
+
print(user["name"], user["age"])
|
|
106
|
+
|
|
107
|
+
# Update
|
|
108
|
+
db.update("users", {"age": 31}, where="name = ?", where_params=("Alice",))
|
|
109
|
+
|
|
110
|
+
# Delete
|
|
111
|
+
db.delete("users", where="name = ?", params=("Bob",))
|
|
112
|
+
|
|
113
|
+
# Raw fetch
|
|
114
|
+
row = db.fetchone("SELECT * FROM users WHERE email = ?", ("alice@example.com",))
|
|
115
|
+
print(row)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### PostgreSQL / MySQL
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
db = DBHandler(
|
|
122
|
+
"postgresql",
|
|
123
|
+
host="localhost",
|
|
124
|
+
port=5432,
|
|
125
|
+
database="mydb",
|
|
126
|
+
user="admin",
|
|
127
|
+
password="secret",
|
|
128
|
+
)
|
|
129
|
+
db.connect()
|
|
130
|
+
# ... same API as SQLite ...
|
|
131
|
+
db.disconnect()
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
### QueryBuilder — fluent SQL construction
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from dbhandler import DBHandler, QueryBuilder
|
|
140
|
+
|
|
141
|
+
with DBHandler("sqlite", database="app.db") as db:
|
|
142
|
+
|
|
143
|
+
# SELECT
|
|
144
|
+
sql, params = (
|
|
145
|
+
QueryBuilder("users")
|
|
146
|
+
.select("id", "name", "email")
|
|
147
|
+
.where("age > ?", 18)
|
|
148
|
+
.order_by("name ASC")
|
|
149
|
+
.limit(10)
|
|
150
|
+
.build()
|
|
151
|
+
)
|
|
152
|
+
rows = db.fetchall(sql, params)
|
|
153
|
+
|
|
154
|
+
# INSERT
|
|
155
|
+
sql, params = QueryBuilder("users").insert(name="Dave", email="d@d.com", age=22).build()
|
|
156
|
+
db.execute(sql, params)
|
|
157
|
+
|
|
158
|
+
# UPDATE
|
|
159
|
+
sql, params = (
|
|
160
|
+
QueryBuilder("users")
|
|
161
|
+
.update(email="dave@new.com")
|
|
162
|
+
.where("name = ?", "Dave")
|
|
163
|
+
.build()
|
|
164
|
+
)
|
|
165
|
+
db.execute(sql, params)
|
|
166
|
+
|
|
167
|
+
# DELETE
|
|
168
|
+
sql, params = QueryBuilder("users").delete().where("id = ?", 99).build()
|
|
169
|
+
db.execute(sql, params)
|
|
170
|
+
|
|
171
|
+
db.commit()
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### BaseModel — ORM-style interface
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from dbhandler import DBHandler, BaseModel
|
|
180
|
+
from dbhandler.models import Field
|
|
181
|
+
|
|
182
|
+
class User(BaseModel):
|
|
183
|
+
__table__ = "users"
|
|
184
|
+
|
|
185
|
+
id = Field(int, primary_key=True)
|
|
186
|
+
name = Field(str, nullable=False)
|
|
187
|
+
email = Field(str, nullable=False, unique=True)
|
|
188
|
+
age = Field(int, default=0)
|
|
189
|
+
|
|
190
|
+
db = DBHandler("sqlite", database="app.db")
|
|
191
|
+
db.connect()
|
|
192
|
+
|
|
193
|
+
User.__db__ = db
|
|
194
|
+
User.create_table()
|
|
195
|
+
|
|
196
|
+
# Create
|
|
197
|
+
alice = User(name="Alice", email="alice@example.com", age=30)
|
|
198
|
+
alice.save()
|
|
199
|
+
|
|
200
|
+
# Read
|
|
201
|
+
all_users = User.all()
|
|
202
|
+
alice = User.get(id=1)
|
|
203
|
+
adults = User.filter("age >= ?", (18,))
|
|
204
|
+
total = User.count()
|
|
205
|
+
|
|
206
|
+
# Update
|
|
207
|
+
alice.age = 31
|
|
208
|
+
alice.save()
|
|
209
|
+
|
|
210
|
+
# Delete
|
|
211
|
+
alice.delete()
|
|
212
|
+
|
|
213
|
+
db.disconnect()
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
### Transactions
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
with DBHandler("sqlite", database="app.db") as db:
|
|
222
|
+
with db.transaction():
|
|
223
|
+
db.insert("orders", {"user_id": 1, "total": 99.99})
|
|
224
|
+
db.insert("order_items", {"order_id": 1, "product_id": 42, "qty": 2})
|
|
225
|
+
# committed automatically; rolled back on any exception
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Schema Utilities
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
db.table_exists("users") # → True / False
|
|
234
|
+
db.get_tables() # → ["users", "orders", ...]
|
|
235
|
+
db.get_columns("users") # → [{"name": "id", "type": "INTEGER", ...}, ...]
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Running Tests
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
pip install ".[dev]"
|
|
244
|
+
pytest tests/ -v --cov=dbhandler
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## License
|
|
250
|
+
|
|
251
|
+
MIT
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# dbhandler
|
|
2
|
+
|
|
3
|
+
A lightweight Python package for managing **SQLite**, **PostgreSQL**, and **MySQL** databases — with a fluent query builder and an ORM-style model layer.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# SQLite only (no extra dependencies)
|
|
11
|
+
pip install .
|
|
12
|
+
|
|
13
|
+
# With PostgreSQL support
|
|
14
|
+
pip install ".[postgresql]"
|
|
15
|
+
|
|
16
|
+
# With MySQL support
|
|
17
|
+
pip install ".[mysql]"
|
|
18
|
+
|
|
19
|
+
# Everything
|
|
20
|
+
pip install ".[all]"
|
|
21
|
+
|
|
22
|
+
# Development tools
|
|
23
|
+
pip install ".[dev]"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
### DBHandler — direct SQL
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from dbhandler import DBHandler
|
|
34
|
+
|
|
35
|
+
# SQLite (in-memory)
|
|
36
|
+
with DBHandler("sqlite", database=":memory:") as db:
|
|
37
|
+
db.execute("""
|
|
38
|
+
CREATE TABLE users (
|
|
39
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
40
|
+
name TEXT NOT NULL,
|
|
41
|
+
email TEXT NOT NULL UNIQUE,
|
|
42
|
+
age INTEGER DEFAULT 0
|
|
43
|
+
)
|
|
44
|
+
""")
|
|
45
|
+
|
|
46
|
+
# Insert a single row
|
|
47
|
+
db.insert("users", {"name": "Alice", "email": "alice@example.com", "age": 30})
|
|
48
|
+
|
|
49
|
+
# Insert many rows
|
|
50
|
+
db.insert_many("users", [
|
|
51
|
+
{"name": "Bob", "email": "bob@example.com", "age": 25},
|
|
52
|
+
{"name": "Carol", "email": "carol@example.com", "age": 35},
|
|
53
|
+
])
|
|
54
|
+
|
|
55
|
+
# Select with a WHERE clause
|
|
56
|
+
adults = db.select("users", where="age >= ?", params=(30,), order_by="name ASC")
|
|
57
|
+
for user in adults:
|
|
58
|
+
print(user["name"], user["age"])
|
|
59
|
+
|
|
60
|
+
# Update
|
|
61
|
+
db.update("users", {"age": 31}, where="name = ?", where_params=("Alice",))
|
|
62
|
+
|
|
63
|
+
# Delete
|
|
64
|
+
db.delete("users", where="name = ?", params=("Bob",))
|
|
65
|
+
|
|
66
|
+
# Raw fetch
|
|
67
|
+
row = db.fetchone("SELECT * FROM users WHERE email = ?", ("alice@example.com",))
|
|
68
|
+
print(row)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### PostgreSQL / MySQL
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
db = DBHandler(
|
|
75
|
+
"postgresql",
|
|
76
|
+
host="localhost",
|
|
77
|
+
port=5432,
|
|
78
|
+
database="mydb",
|
|
79
|
+
user="admin",
|
|
80
|
+
password="secret",
|
|
81
|
+
)
|
|
82
|
+
db.connect()
|
|
83
|
+
# ... same API as SQLite ...
|
|
84
|
+
db.disconnect()
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### QueryBuilder — fluent SQL construction
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from dbhandler import DBHandler, QueryBuilder
|
|
93
|
+
|
|
94
|
+
with DBHandler("sqlite", database="app.db") as db:
|
|
95
|
+
|
|
96
|
+
# SELECT
|
|
97
|
+
sql, params = (
|
|
98
|
+
QueryBuilder("users")
|
|
99
|
+
.select("id", "name", "email")
|
|
100
|
+
.where("age > ?", 18)
|
|
101
|
+
.order_by("name ASC")
|
|
102
|
+
.limit(10)
|
|
103
|
+
.build()
|
|
104
|
+
)
|
|
105
|
+
rows = db.fetchall(sql, params)
|
|
106
|
+
|
|
107
|
+
# INSERT
|
|
108
|
+
sql, params = QueryBuilder("users").insert(name="Dave", email="d@d.com", age=22).build()
|
|
109
|
+
db.execute(sql, params)
|
|
110
|
+
|
|
111
|
+
# UPDATE
|
|
112
|
+
sql, params = (
|
|
113
|
+
QueryBuilder("users")
|
|
114
|
+
.update(email="dave@new.com")
|
|
115
|
+
.where("name = ?", "Dave")
|
|
116
|
+
.build()
|
|
117
|
+
)
|
|
118
|
+
db.execute(sql, params)
|
|
119
|
+
|
|
120
|
+
# DELETE
|
|
121
|
+
sql, params = QueryBuilder("users").delete().where("id = ?", 99).build()
|
|
122
|
+
db.execute(sql, params)
|
|
123
|
+
|
|
124
|
+
db.commit()
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
### BaseModel — ORM-style interface
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from dbhandler import DBHandler, BaseModel
|
|
133
|
+
from dbhandler.models import Field
|
|
134
|
+
|
|
135
|
+
class User(BaseModel):
|
|
136
|
+
__table__ = "users"
|
|
137
|
+
|
|
138
|
+
id = Field(int, primary_key=True)
|
|
139
|
+
name = Field(str, nullable=False)
|
|
140
|
+
email = Field(str, nullable=False, unique=True)
|
|
141
|
+
age = Field(int, default=0)
|
|
142
|
+
|
|
143
|
+
db = DBHandler("sqlite", database="app.db")
|
|
144
|
+
db.connect()
|
|
145
|
+
|
|
146
|
+
User.__db__ = db
|
|
147
|
+
User.create_table()
|
|
148
|
+
|
|
149
|
+
# Create
|
|
150
|
+
alice = User(name="Alice", email="alice@example.com", age=30)
|
|
151
|
+
alice.save()
|
|
152
|
+
|
|
153
|
+
# Read
|
|
154
|
+
all_users = User.all()
|
|
155
|
+
alice = User.get(id=1)
|
|
156
|
+
adults = User.filter("age >= ?", (18,))
|
|
157
|
+
total = User.count()
|
|
158
|
+
|
|
159
|
+
# Update
|
|
160
|
+
alice.age = 31
|
|
161
|
+
alice.save()
|
|
162
|
+
|
|
163
|
+
# Delete
|
|
164
|
+
alice.delete()
|
|
165
|
+
|
|
166
|
+
db.disconnect()
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### Transactions
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
with DBHandler("sqlite", database="app.db") as db:
|
|
175
|
+
with db.transaction():
|
|
176
|
+
db.insert("orders", {"user_id": 1, "total": 99.99})
|
|
177
|
+
db.insert("order_items", {"order_id": 1, "product_id": 42, "qty": 2})
|
|
178
|
+
# committed automatically; rolled back on any exception
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Schema Utilities
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
db.table_exists("users") # → True / False
|
|
187
|
+
db.get_tables() # → ["users", "orders", ...]
|
|
188
|
+
db.get_columns("users") # → [{"name": "id", "type": "INTEGER", ...}, ...]
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Running Tests
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
pip install ".[dev]"
|
|
197
|
+
pytest tests/ -v --cov=dbhandler
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
MIT
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: databasesupasafe
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A lightweight Python package for managing SQLite, PostgreSQL, and MySQL databases.
|
|
5
|
+
Home-page: https://github.com/yourname/dbhandler
|
|
6
|
+
Author: dbhandler contributors
|
|
7
|
+
Author-email: you@example.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: Topic :: Database
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: >=3.8
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: api-feature
|
|
23
|
+
Provides-Extra: postgresql
|
|
24
|
+
Requires-Dist: psycopg2-binary>=2.9; extra == "postgresql"
|
|
25
|
+
Provides-Extra: mysql
|
|
26
|
+
Requires-Dist: mysql-connector-python>=8.0; extra == "mysql"
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: psycopg2-binary>=2.9; extra == "all"
|
|
29
|
+
Requires-Dist: mysql-connector-python>=8.0; extra == "all"
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
33
|
+
Requires-Dist: black; extra == "dev"
|
|
34
|
+
Requires-Dist: isort; extra == "dev"
|
|
35
|
+
Requires-Dist: mypy; extra == "dev"
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: author-email
|
|
38
|
+
Dynamic: classifier
|
|
39
|
+
Dynamic: description
|
|
40
|
+
Dynamic: description-content-type
|
|
41
|
+
Dynamic: home-page
|
|
42
|
+
Dynamic: license
|
|
43
|
+
Dynamic: provides-extra
|
|
44
|
+
Dynamic: requires-dist
|
|
45
|
+
Dynamic: requires-python
|
|
46
|
+
Dynamic: summary
|
|
47
|
+
|
|
48
|
+
# dbhandler
|
|
49
|
+
|
|
50
|
+
A lightweight Python package for managing **SQLite**, **PostgreSQL**, and **MySQL** databases — with a fluent query builder and an ORM-style model layer.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# SQLite only (no extra dependencies)
|
|
58
|
+
pip install .
|
|
59
|
+
|
|
60
|
+
# With PostgreSQL support
|
|
61
|
+
pip install ".[postgresql]"
|
|
62
|
+
|
|
63
|
+
# With MySQL support
|
|
64
|
+
pip install ".[mysql]"
|
|
65
|
+
|
|
66
|
+
# Everything
|
|
67
|
+
pip install ".[all]"
|
|
68
|
+
|
|
69
|
+
# Development tools
|
|
70
|
+
pip install ".[dev]"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Quick Start
|
|
76
|
+
|
|
77
|
+
### DBHandler — direct SQL
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from dbhandler import DBHandler
|
|
81
|
+
|
|
82
|
+
# SQLite (in-memory)
|
|
83
|
+
with DBHandler("sqlite", database=":memory:") as db:
|
|
84
|
+
db.execute("""
|
|
85
|
+
CREATE TABLE users (
|
|
86
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
87
|
+
name TEXT NOT NULL,
|
|
88
|
+
email TEXT NOT NULL UNIQUE,
|
|
89
|
+
age INTEGER DEFAULT 0
|
|
90
|
+
)
|
|
91
|
+
""")
|
|
92
|
+
|
|
93
|
+
# Insert a single row
|
|
94
|
+
db.insert("users", {"name": "Alice", "email": "alice@example.com", "age": 30})
|
|
95
|
+
|
|
96
|
+
# Insert many rows
|
|
97
|
+
db.insert_many("users", [
|
|
98
|
+
{"name": "Bob", "email": "bob@example.com", "age": 25},
|
|
99
|
+
{"name": "Carol", "email": "carol@example.com", "age": 35},
|
|
100
|
+
])
|
|
101
|
+
|
|
102
|
+
# Select with a WHERE clause
|
|
103
|
+
adults = db.select("users", where="age >= ?", params=(30,), order_by="name ASC")
|
|
104
|
+
for user in adults:
|
|
105
|
+
print(user["name"], user["age"])
|
|
106
|
+
|
|
107
|
+
# Update
|
|
108
|
+
db.update("users", {"age": 31}, where="name = ?", where_params=("Alice",))
|
|
109
|
+
|
|
110
|
+
# Delete
|
|
111
|
+
db.delete("users", where="name = ?", params=("Bob",))
|
|
112
|
+
|
|
113
|
+
# Raw fetch
|
|
114
|
+
row = db.fetchone("SELECT * FROM users WHERE email = ?", ("alice@example.com",))
|
|
115
|
+
print(row)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### PostgreSQL / MySQL
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
db = DBHandler(
|
|
122
|
+
"postgresql",
|
|
123
|
+
host="localhost",
|
|
124
|
+
port=5432,
|
|
125
|
+
database="mydb",
|
|
126
|
+
user="admin",
|
|
127
|
+
password="secret",
|
|
128
|
+
)
|
|
129
|
+
db.connect()
|
|
130
|
+
# ... same API as SQLite ...
|
|
131
|
+
db.disconnect()
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
### QueryBuilder — fluent SQL construction
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from dbhandler import DBHandler, QueryBuilder
|
|
140
|
+
|
|
141
|
+
with DBHandler("sqlite", database="app.db") as db:
|
|
142
|
+
|
|
143
|
+
# SELECT
|
|
144
|
+
sql, params = (
|
|
145
|
+
QueryBuilder("users")
|
|
146
|
+
.select("id", "name", "email")
|
|
147
|
+
.where("age > ?", 18)
|
|
148
|
+
.order_by("name ASC")
|
|
149
|
+
.limit(10)
|
|
150
|
+
.build()
|
|
151
|
+
)
|
|
152
|
+
rows = db.fetchall(sql, params)
|
|
153
|
+
|
|
154
|
+
# INSERT
|
|
155
|
+
sql, params = QueryBuilder("users").insert(name="Dave", email="d@d.com", age=22).build()
|
|
156
|
+
db.execute(sql, params)
|
|
157
|
+
|
|
158
|
+
# UPDATE
|
|
159
|
+
sql, params = (
|
|
160
|
+
QueryBuilder("users")
|
|
161
|
+
.update(email="dave@new.com")
|
|
162
|
+
.where("name = ?", "Dave")
|
|
163
|
+
.build()
|
|
164
|
+
)
|
|
165
|
+
db.execute(sql, params)
|
|
166
|
+
|
|
167
|
+
# DELETE
|
|
168
|
+
sql, params = QueryBuilder("users").delete().where("id = ?", 99).build()
|
|
169
|
+
db.execute(sql, params)
|
|
170
|
+
|
|
171
|
+
db.commit()
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### BaseModel — ORM-style interface
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from dbhandler import DBHandler, BaseModel
|
|
180
|
+
from dbhandler.models import Field
|
|
181
|
+
|
|
182
|
+
class User(BaseModel):
|
|
183
|
+
__table__ = "users"
|
|
184
|
+
|
|
185
|
+
id = Field(int, primary_key=True)
|
|
186
|
+
name = Field(str, nullable=False)
|
|
187
|
+
email = Field(str, nullable=False, unique=True)
|
|
188
|
+
age = Field(int, default=0)
|
|
189
|
+
|
|
190
|
+
db = DBHandler("sqlite", database="app.db")
|
|
191
|
+
db.connect()
|
|
192
|
+
|
|
193
|
+
User.__db__ = db
|
|
194
|
+
User.create_table()
|
|
195
|
+
|
|
196
|
+
# Create
|
|
197
|
+
alice = User(name="Alice", email="alice@example.com", age=30)
|
|
198
|
+
alice.save()
|
|
199
|
+
|
|
200
|
+
# Read
|
|
201
|
+
all_users = User.all()
|
|
202
|
+
alice = User.get(id=1)
|
|
203
|
+
adults = User.filter("age >= ?", (18,))
|
|
204
|
+
total = User.count()
|
|
205
|
+
|
|
206
|
+
# Update
|
|
207
|
+
alice.age = 31
|
|
208
|
+
alice.save()
|
|
209
|
+
|
|
210
|
+
# Delete
|
|
211
|
+
alice.delete()
|
|
212
|
+
|
|
213
|
+
db.disconnect()
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
### Transactions
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
with DBHandler("sqlite", database="app.db") as db:
|
|
222
|
+
with db.transaction():
|
|
223
|
+
db.insert("orders", {"user_id": 1, "total": 99.99})
|
|
224
|
+
db.insert("order_items", {"order_id": 1, "product_id": 42, "qty": 2})
|
|
225
|
+
# committed automatically; rolled back on any exception
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Schema Utilities
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
db.table_exists("users") # → True / False
|
|
234
|
+
db.get_tables() # → ["users", "orders", ...]
|
|
235
|
+
db.get_columns("users") # → [{"name": "id", "type": "INTEGER", ...}, ...]
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Running Tests
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
pip install ".[dev]"
|
|
244
|
+
pytest tests/ -v --cov=dbhandler
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## License
|
|
250
|
+
|
|
251
|
+
MIT
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
databasesupasafe.egg-info/PKG-INFO
|
|
4
|
+
databasesupasafe.egg-info/SOURCES.txt
|
|
5
|
+
databasesupasafe.egg-info/dependency_links.txt
|
|
6
|
+
databasesupasafe.egg-info/not-zip-safe
|
|
7
|
+
databasesupasafe.egg-info/requires.txt
|
|
8
|
+
databasesupasafe.egg-info/top_level.txt
|
|
9
|
+
dbhandler/__init__.py
|
|
10
|
+
dbhandler/core.py
|
|
11
|
+
dbhandler/exceptions.py
|
|
12
|
+
dbhandler/models.py
|
|
13
|
+
dbhandler/query.py
|
|
14
|
+
tests/test_dbhandler.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|