py-flexo 0.1.0__tar.gz → 0.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.
- {py_flexo-0.1.0 → py_flexo-0.2.0}/PKG-INFO +1 -1
- py_flexo-0.2.0/py_flexo/orm.py +199 -0
- {py_flexo-0.1.0 → py_flexo-0.2.0}/py_flexo.egg-info/PKG-INFO +1 -1
- {py_flexo-0.1.0 → py_flexo-0.2.0}/py_flexo.egg-info/SOURCES.txt +1 -0
- {py_flexo-0.1.0 → py_flexo-0.2.0}/pyproject.toml +1 -1
- {py_flexo-0.1.0 → py_flexo-0.2.0}/README.md +0 -0
- {py_flexo-0.1.0 → py_flexo-0.2.0}/py_flexo/__init__.py +0 -0
- {py_flexo-0.1.0 → py_flexo-0.2.0}/py_flexo/app.py +0 -0
- {py_flexo-0.1.0 → py_flexo-0.2.0}/py_flexo/middleware.py +0 -0
- {py_flexo-0.1.0 → py_flexo-0.2.0}/py_flexo/response.py +0 -0
- {py_flexo-0.1.0 → py_flexo-0.2.0}/py_flexo.egg-info/dependency_links.txt +0 -0
- {py_flexo-0.1.0 → py_flexo-0.2.0}/py_flexo.egg-info/requires.txt +0 -0
- {py_flexo-0.1.0 → py_flexo-0.2.0}/py_flexo.egg-info/top_level.txt +0 -0
- {py_flexo-0.1.0 → py_flexo-0.2.0}/setup.cfg +0 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import sqlite3
|
|
2
|
+
import inspect
|
|
3
|
+
|
|
4
|
+
class Database:
|
|
5
|
+
def __init__(self, path):
|
|
6
|
+
self.conn = sqlite3.Connection(path)
|
|
7
|
+
|
|
8
|
+
@property
|
|
9
|
+
def tables(self):
|
|
10
|
+
result = self.conn.execute("SELECT name FROM sqlite_master WHERE type='table';")
|
|
11
|
+
return [row[0] for row in result.fetchall()]
|
|
12
|
+
|
|
13
|
+
def create(self, table):
|
|
14
|
+
self.conn.execute(table._get_create_sql())
|
|
15
|
+
|
|
16
|
+
def save(self, instance):
|
|
17
|
+
sql, values = instance._insert_sql()
|
|
18
|
+
cursor = self.conn.execute(sql, values)
|
|
19
|
+
self.conn.commit()
|
|
20
|
+
instance._data["id"] = cursor.lastrowid
|
|
21
|
+
|
|
22
|
+
def all(self, table):
|
|
23
|
+
sql, fields = table._get_select_all_sql()
|
|
24
|
+
result = []
|
|
25
|
+
for row in self.conn.execute(sql).fetchall():
|
|
26
|
+
instance = table()
|
|
27
|
+
for field, value in zip(fields, row):
|
|
28
|
+
if field.endswith("_id"):
|
|
29
|
+
field = field[:-3]
|
|
30
|
+
fk = getattr(table, field)
|
|
31
|
+
value = self.get(fk.table, value)
|
|
32
|
+
setattr(instance, field, value)
|
|
33
|
+
|
|
34
|
+
result.append(instance)
|
|
35
|
+
|
|
36
|
+
return result
|
|
37
|
+
|
|
38
|
+
def get(self, table, id):
|
|
39
|
+
sql, fields = table._get_by_id_sql(id = id)
|
|
40
|
+
result = self.conn.execute(sql).fetchone()
|
|
41
|
+
if result is None:
|
|
42
|
+
raise Exception(f"{table.__name__} not found for id {id}")
|
|
43
|
+
instance = table()
|
|
44
|
+
for field, value in zip(fields, result):
|
|
45
|
+
if field.endswith("_id"):
|
|
46
|
+
field = field[:-3]
|
|
47
|
+
fk = getattr(table, field)
|
|
48
|
+
value = self.get(fk.table, value)
|
|
49
|
+
setattr(instance, field, value)
|
|
50
|
+
return instance
|
|
51
|
+
|
|
52
|
+
def update(self, instance):
|
|
53
|
+
sql, values = instance._update_sql()
|
|
54
|
+
self.conn.execute(sql, values)
|
|
55
|
+
self.conn.commit()
|
|
56
|
+
|
|
57
|
+
def delete(self, instance):
|
|
58
|
+
sql= instance._delete_sql()
|
|
59
|
+
self.conn.execute(sql)
|
|
60
|
+
self.conn.commit()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class Table:
|
|
64
|
+
def __init__(self, **kwargs):
|
|
65
|
+
self._data = {
|
|
66
|
+
"id": None
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
for name, value in kwargs.items():
|
|
70
|
+
self._data[name] = value
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def _get_create_sql(cls):
|
|
75
|
+
CREATE_TABLE_SQL = 'CREATE TABLE IF NOT EXISTS {name} ({fields});'
|
|
76
|
+
fields = [
|
|
77
|
+
'id INTEGER PRIMARY KEY AUTOINCREMENT'
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
for name, col in inspect.getmembers(cls):
|
|
81
|
+
if isinstance(col, Column):
|
|
82
|
+
fields.append(f"{name} {col.sql_type}")
|
|
83
|
+
|
|
84
|
+
elif isinstance(col, ForeignKey):
|
|
85
|
+
fields.append(f"{name}_id INTEGER")
|
|
86
|
+
name = cls.__name__.lower()
|
|
87
|
+
fields = ", ".join(fields)
|
|
88
|
+
|
|
89
|
+
return CREATE_TABLE_SQL.format(name=name, fields=fields)
|
|
90
|
+
|
|
91
|
+
def _insert_sql(self):
|
|
92
|
+
INSERT_SQL = 'INSERT INTO {name} ({fields}) VALUES ({placeholders});'
|
|
93
|
+
cls = self.__class__
|
|
94
|
+
fields = []
|
|
95
|
+
placeholders = []
|
|
96
|
+
values = []
|
|
97
|
+
|
|
98
|
+
for name, col in inspect.getmembers(cls):
|
|
99
|
+
if isinstance(col, Column):
|
|
100
|
+
fields.append(name)
|
|
101
|
+
placeholders.append('?')
|
|
102
|
+
values.append(self._data[name])
|
|
103
|
+
elif isinstance(col, ForeignKey):
|
|
104
|
+
fields.append(f"{name}_id")
|
|
105
|
+
placeholders.append('?')
|
|
106
|
+
values.append(self._data[name].id)
|
|
107
|
+
|
|
108
|
+
fields = ", ".join(fields)
|
|
109
|
+
placeholders = ", ".join(placeholders)
|
|
110
|
+
|
|
111
|
+
name_table = cls.__name__.lower()
|
|
112
|
+
|
|
113
|
+
sql = INSERT_SQL.format(name=name_table, fields=fields, placeholders=placeholders)
|
|
114
|
+
|
|
115
|
+
return sql, values
|
|
116
|
+
|
|
117
|
+
def __getattribute__(self, name):
|
|
118
|
+
data = super().__getattribute__('_data')
|
|
119
|
+
if name in data:
|
|
120
|
+
return self._data[name]
|
|
121
|
+
|
|
122
|
+
return super().__getattribute__(name)
|
|
123
|
+
|
|
124
|
+
def __setattr__(self, name, value):
|
|
125
|
+
super().__setattr__(name, value)
|
|
126
|
+
if name in self._data:
|
|
127
|
+
self._data[name] = value
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@classmethod
|
|
131
|
+
def _get_select_all_sql(cls):
|
|
132
|
+
SELECT_ALL_SQL = 'SELECT {fields} FROM {name};'
|
|
133
|
+
fields = ['id']
|
|
134
|
+
for name, col in inspect.getmembers(cls):
|
|
135
|
+
if isinstance(col, Column):
|
|
136
|
+
fields.append(name)
|
|
137
|
+
elif isinstance(col, ForeignKey):
|
|
138
|
+
fields.append(f"{name}_id")
|
|
139
|
+
name = cls.__name__.lower()
|
|
140
|
+
sql = SELECT_ALL_SQL.format(fields=', '.join(fields), name=name)
|
|
141
|
+
|
|
142
|
+
return sql, fields
|
|
143
|
+
|
|
144
|
+
@classmethod
|
|
145
|
+
def _get_by_id_sql(cls, id):
|
|
146
|
+
SELECT_BY_ID_SQL = 'SELECT {fields} FROM {name} WHERE id = {id};'
|
|
147
|
+
fields = ['id']
|
|
148
|
+
for name, col in inspect.getmembers(cls):
|
|
149
|
+
if isinstance(col, Column):
|
|
150
|
+
fields.append(name)
|
|
151
|
+
elif isinstance(col, ForeignKey):
|
|
152
|
+
fields.append(f"{name}_id")
|
|
153
|
+
name = cls.__name__.lower()
|
|
154
|
+
sql = SELECT_BY_ID_SQL.format(fields=', '.join(fields), name=name, id=id)
|
|
155
|
+
|
|
156
|
+
return sql, fields
|
|
157
|
+
|
|
158
|
+
def _update_sql(self):
|
|
159
|
+
UPDATE_SQL = 'UPDATE {name} SET {fields} WHERE id = {id};'
|
|
160
|
+
fields = []
|
|
161
|
+
values = []
|
|
162
|
+
for name, col in inspect.getmembers(self.__class__):
|
|
163
|
+
if isinstance(col, Column):
|
|
164
|
+
fields.append(f"{name} = ?")
|
|
165
|
+
values.append(getattr(self, name))
|
|
166
|
+
elif isinstance(col, ForeignKey):
|
|
167
|
+
fields.append(f"{name}_id = ?")
|
|
168
|
+
values.append(getattr(col.table, 'id'))
|
|
169
|
+
|
|
170
|
+
name = self.__class__.__name__.lower()
|
|
171
|
+
sql = UPDATE_SQL.format(fields=', '.join(fields), name=name, id=self.id)
|
|
172
|
+
|
|
173
|
+
return sql, values
|
|
174
|
+
|
|
175
|
+
def _delete_sql(self):
|
|
176
|
+
DELETE_SQL = 'DELETE FROM {name} WHERE id = {id};'
|
|
177
|
+
name = self.__class__.__name__.lower()
|
|
178
|
+
sql = DELETE_SQL.format(name=name, id=self.id)
|
|
179
|
+
|
|
180
|
+
return sql
|
|
181
|
+
|
|
182
|
+
class Column:
|
|
183
|
+
def __init__(self, column_type):
|
|
184
|
+
self.type = column_type
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def sql_type(self):
|
|
188
|
+
SQLITE_TYPE_MAP = {
|
|
189
|
+
int: 'INTEGER',
|
|
190
|
+
float: 'REAL',
|
|
191
|
+
bool: 'INTEGER',
|
|
192
|
+
str: 'TEXT'
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return SQLITE_TYPE_MAP[self.type]
|
|
196
|
+
|
|
197
|
+
class ForeignKey:
|
|
198
|
+
def __init__(self, table):
|
|
199
|
+
self.table = table
|
|
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
|