PyCyphORM 0.1.3__tar.gz → 26.5.25__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.
- pycyphorm-26.5.25/PKG-INFO +69 -0
- pycyphorm-26.5.25/README.md +59 -0
- pycyphorm-26.5.25/pyproject.toml +22 -0
- pycyphorm-26.5.25/src/PyCyphORM.egg-info/PKG-INFO +69 -0
- pycyphorm-26.5.25/src/PyCyphORM.egg-info/SOURCES.txt +13 -0
- pycyphorm-26.5.25/src/PyCyphORM.egg-info/entry_points.txt +2 -0
- pycyphorm-26.5.25/src/PyCyphORM.egg-info/requires.txt +1 -0
- pycyphorm-26.5.25/src/PyCyphORM.egg-info/top_level.txt +1 -0
- pycyphorm-26.5.25/src/pyorm/__init__.py +4 -0
- {PyCyphORM-0.1.3/src/PyCyphORM/lib → pycyphorm-26.5.25/src/pyorm}/adapter.py +0 -2
- {PyCyphORM-0.1.3/src/PyCyphORM → pycyphorm-26.5.25/src/pyorm}/cli.py +13 -13
- {PyCyphORM-0.1.3/src/PyCyphORM/lib → pycyphorm-26.5.25/src/pyorm}/orm.py +14 -23
- pycyphorm-26.5.25/tests/test_crud.py +99 -0
- PyCyphORM-0.1.3/PKG-INFO +0 -54
- PyCyphORM-0.1.3/PyCyphORM.egg-info/PKG-INFO +0 -54
- PyCyphORM-0.1.3/PyCyphORM.egg-info/SOURCES.txt +0 -12
- PyCyphORM-0.1.3/PyCyphORM.egg-info/entry_points.txt +0 -2
- PyCyphORM-0.1.3/PyCyphORM.egg-info/top_level.txt +0 -1
- PyCyphORM-0.1.3/README.md +0 -45
- PyCyphORM-0.1.3/setup.py +0 -27
- PyCyphORM-0.1.3/src/PyCyphORM/__init__.py +0 -3
- PyCyphORM-0.1.3/src/PyCyphORM/lib/__init__.py +0 -2
- {PyCyphORM-0.1.3 → pycyphorm-26.5.25}/setup.cfg +0 -0
- {PyCyphORM-0.1.3 → pycyphorm-26.5.25/src}/PyCyphORM.egg-info/dependency_links.txt +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: PyCyphORM
|
|
3
|
+
Version: 26.5.25
|
|
4
|
+
Summary: A simple in-memory encrypted ORM for SQLite3
|
|
5
|
+
Author-email: Joao Martins <joaomartins@lts.pt>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: cryptography>=41.0.0
|
|
10
|
+
|
|
11
|
+
# PyCyphORM
|
|
12
|
+
|
|
13
|
+
A simple in-memory encrypted ORM for SQLite3.
|
|
14
|
+
|
|
15
|
+
The database lives in memory while in use and is persisted to disk as a gzipped,
|
|
16
|
+
Fernet-encrypted blob. Keys are derived from a password and salt with PBKDF2-HMAC-SHA256.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install PyCyphORM
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## CLI
|
|
25
|
+
|
|
26
|
+
Generate a `.pyorm` config (random salt + password) in the current directory:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pyorm --init 1
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Decrypt an encrypted database file to `<file>.decoded.db`:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pyorm --decrypt path/to/db
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Library usage
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from pyorm import ORM, load_config
|
|
42
|
+
|
|
43
|
+
cnf = load_config(".pyorm")
|
|
44
|
+
|
|
45
|
+
orm = ORM("users.db", cnf["PASSWORD"], cnf["SALT"], {
|
|
46
|
+
"users": {
|
|
47
|
+
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
|
|
48
|
+
"name": "TEXT NOT NULL",
|
|
49
|
+
"email": "TEXT NOT NULL",
|
|
50
|
+
"age": "INT NOT NULL",
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
users = orm.model("users")
|
|
55
|
+
users.insert({"name": "Alice", "email": "alice@example.com", "age": 30})
|
|
56
|
+
users.update({"name": "Alice"}, {"age": 31})
|
|
57
|
+
print(users.find())
|
|
58
|
+
print(users.first({"name": "Alice"}))
|
|
59
|
+
users.delete({"name": "Alice"})
|
|
60
|
+
|
|
61
|
+
orm.save()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`orm.save()` writes the encrypted snapshot back to disk. Without it, changes
|
|
65
|
+
remain in memory only.
|
|
66
|
+
|
|
67
|
+
## License
|
|
68
|
+
|
|
69
|
+
MIT
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# PyCyphORM
|
|
2
|
+
|
|
3
|
+
A simple in-memory encrypted ORM for SQLite3.
|
|
4
|
+
|
|
5
|
+
The database lives in memory while in use and is persisted to disk as a gzipped,
|
|
6
|
+
Fernet-encrypted blob. Keys are derived from a password and salt with PBKDF2-HMAC-SHA256.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install PyCyphORM
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## CLI
|
|
15
|
+
|
|
16
|
+
Generate a `.pyorm` config (random salt + password) in the current directory:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pyorm --init 1
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Decrypt an encrypted database file to `<file>.decoded.db`:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pyorm --decrypt path/to/db
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Library usage
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from pyorm import ORM, load_config
|
|
32
|
+
|
|
33
|
+
cnf = load_config(".pyorm")
|
|
34
|
+
|
|
35
|
+
orm = ORM("users.db", cnf["PASSWORD"], cnf["SALT"], {
|
|
36
|
+
"users": {
|
|
37
|
+
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
|
|
38
|
+
"name": "TEXT NOT NULL",
|
|
39
|
+
"email": "TEXT NOT NULL",
|
|
40
|
+
"age": "INT NOT NULL",
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
users = orm.model("users")
|
|
45
|
+
users.insert({"name": "Alice", "email": "alice@example.com", "age": 30})
|
|
46
|
+
users.update({"name": "Alice"}, {"age": 31})
|
|
47
|
+
print(users.find())
|
|
48
|
+
print(users.first({"name": "Alice"}))
|
|
49
|
+
users.delete({"name": "Alice"})
|
|
50
|
+
|
|
51
|
+
orm.save()
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`orm.save()` writes the encrypted snapshot back to disk. Without it, changes
|
|
55
|
+
remain in memory only.
|
|
56
|
+
|
|
57
|
+
## License
|
|
58
|
+
|
|
59
|
+
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "PyCyphORM"
|
|
7
|
+
version = "26.5.25"
|
|
8
|
+
description = "A simple in-memory encrypted ORM for SQLite3"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Joao Martins", email = "joaomartins@lts.pt" }]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"cryptography>=41.0.0",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.scripts]
|
|
18
|
+
pyorm = "pyorm.cli:cli"
|
|
19
|
+
|
|
20
|
+
[tool.setuptools.packages.find]
|
|
21
|
+
where = ["src"]
|
|
22
|
+
include = ["pyorm*"]
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: PyCyphORM
|
|
3
|
+
Version: 26.5.25
|
|
4
|
+
Summary: A simple in-memory encrypted ORM for SQLite3
|
|
5
|
+
Author-email: Joao Martins <joaomartins@lts.pt>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: cryptography>=41.0.0
|
|
10
|
+
|
|
11
|
+
# PyCyphORM
|
|
12
|
+
|
|
13
|
+
A simple in-memory encrypted ORM for SQLite3.
|
|
14
|
+
|
|
15
|
+
The database lives in memory while in use and is persisted to disk as a gzipped,
|
|
16
|
+
Fernet-encrypted blob. Keys are derived from a password and salt with PBKDF2-HMAC-SHA256.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install PyCyphORM
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## CLI
|
|
25
|
+
|
|
26
|
+
Generate a `.pyorm` config (random salt + password) in the current directory:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pyorm --init 1
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Decrypt an encrypted database file to `<file>.decoded.db`:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pyorm --decrypt path/to/db
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Library usage
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from pyorm import ORM, load_config
|
|
42
|
+
|
|
43
|
+
cnf = load_config(".pyorm")
|
|
44
|
+
|
|
45
|
+
orm = ORM("users.db", cnf["PASSWORD"], cnf["SALT"], {
|
|
46
|
+
"users": {
|
|
47
|
+
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
|
|
48
|
+
"name": "TEXT NOT NULL",
|
|
49
|
+
"email": "TEXT NOT NULL",
|
|
50
|
+
"age": "INT NOT NULL",
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
users = orm.model("users")
|
|
55
|
+
users.insert({"name": "Alice", "email": "alice@example.com", "age": 30})
|
|
56
|
+
users.update({"name": "Alice"}, {"age": 31})
|
|
57
|
+
print(users.find())
|
|
58
|
+
print(users.first({"name": "Alice"}))
|
|
59
|
+
users.delete({"name": "Alice"})
|
|
60
|
+
|
|
61
|
+
orm.save()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`orm.save()` writes the encrypted snapshot back to disk. Without it, changes
|
|
65
|
+
remain in memory only.
|
|
66
|
+
|
|
67
|
+
## License
|
|
68
|
+
|
|
69
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/PyCyphORM.egg-info/PKG-INFO
|
|
4
|
+
src/PyCyphORM.egg-info/SOURCES.txt
|
|
5
|
+
src/PyCyphORM.egg-info/dependency_links.txt
|
|
6
|
+
src/PyCyphORM.egg-info/entry_points.txt
|
|
7
|
+
src/PyCyphORM.egg-info/requires.txt
|
|
8
|
+
src/PyCyphORM.egg-info/top_level.txt
|
|
9
|
+
src/pyorm/__init__.py
|
|
10
|
+
src/pyorm/adapter.py
|
|
11
|
+
src/pyorm/cli.py
|
|
12
|
+
src/pyorm/orm.py
|
|
13
|
+
tests/test_crud.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cryptography>=41.0.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyorm
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
#!/bin/env python3
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
2
|
|
|
3
3
|
import argparse
|
|
4
|
-
|
|
5
|
-
from os import urandom, path
|
|
6
|
-
from base64 import b16encode
|
|
4
|
+
import json
|
|
7
5
|
import random
|
|
6
|
+
from base64 import b16encode
|
|
7
|
+
from os import urandom, path
|
|
8
8
|
|
|
9
|
-
import json
|
|
10
9
|
|
|
11
10
|
def random_password():
|
|
12
11
|
password = ""
|
|
@@ -15,14 +14,15 @@ def random_password():
|
|
|
15
14
|
password = password + random.choice(characters)
|
|
16
15
|
return password
|
|
17
16
|
|
|
17
|
+
|
|
18
18
|
parser = argparse.ArgumentParser(
|
|
19
|
-
prog
|
|
20
|
-
description
|
|
19
|
+
prog='pyorm',
|
|
20
|
+
description='A simple python orm',
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
parser.add_argument("-i", "--init", metavar="INIT", help="Initialize Salt and Password for Encrypted Database")
|
|
24
|
-
parser.add_argument("-d", "--decrypt", metavar="FILEPATH", help="
|
|
25
|
-
|
|
24
|
+
parser.add_argument("-d", "--decrypt", metavar="FILEPATH", help="Decrypt SQLite Database")
|
|
25
|
+
|
|
26
26
|
|
|
27
27
|
def cli():
|
|
28
28
|
args = vars(parser.parse_args())
|
|
@@ -35,11 +35,11 @@ def cli():
|
|
|
35
35
|
|
|
36
36
|
elif args['decrypt']:
|
|
37
37
|
if path.exists(path.abspath(args['decrypt'])):
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
from .adapter import decrypt_cdb, load_config
|
|
39
|
+
|
|
41
40
|
cnf = load_config(".pyorm")
|
|
42
41
|
decrypt_cdb(path.abspath(args['decrypt']), cnf["PASSWORD"], cnf["SALT"])
|
|
43
42
|
|
|
44
43
|
|
|
45
|
-
if __name__ == "__main__":
|
|
44
|
+
if __name__ == "__main__":
|
|
45
|
+
cli()
|
|
@@ -45,8 +45,8 @@ class QueryBuilder:
|
|
|
45
45
|
count += 1
|
|
46
46
|
bulk.append("(%s)" % (",".join(values)))
|
|
47
47
|
sql = "INSERT INTO %s (%s) VALUES %s" % (table, ",".join(columns), ",".join(bulk))
|
|
48
|
-
return sql
|
|
49
|
-
|
|
48
|
+
return sql
|
|
49
|
+
|
|
50
50
|
@staticmethod
|
|
51
51
|
def __create_table__(table, schema):
|
|
52
52
|
definition = []
|
|
@@ -66,7 +66,7 @@ class QueryBuilder:
|
|
|
66
66
|
sql += " WHERE %s" % self.__where__(where)
|
|
67
67
|
return sql
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
def __select__(self, table, fields, where=None, orderby=None):
|
|
71
71
|
sql = "SELECT %s FROM %s" % (",".join(fields), table)
|
|
72
72
|
if isinstance(where, dict):
|
|
@@ -78,7 +78,7 @@ class QueryBuilder:
|
|
|
78
78
|
def __delete__(self, table, where):
|
|
79
79
|
sql = "DELETE FROM %s WHERE %s" % (table, self.__where__(where))
|
|
80
80
|
return sql
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
class Model(QueryBuilder):
|
|
83
83
|
|
|
84
84
|
def __init__(self, conn, table, schema):
|
|
@@ -92,7 +92,7 @@ class Model(QueryBuilder):
|
|
|
92
92
|
cur.execute(sql)
|
|
93
93
|
self.conn.commit()
|
|
94
94
|
return cur.rowcount
|
|
95
|
-
|
|
95
|
+
|
|
96
96
|
def up(self):
|
|
97
97
|
sql = self.__create_table__(self.table, self.schema)
|
|
98
98
|
cur = self.conn.cursor()
|
|
@@ -115,7 +115,7 @@ class Model(QueryBuilder):
|
|
|
115
115
|
return cur.rowcount
|
|
116
116
|
|
|
117
117
|
def delete(self, where):
|
|
118
|
-
sql = self.__delete__(self.table, where)
|
|
118
|
+
sql = self.__delete__(self.table, where)
|
|
119
119
|
cur = self.conn.cursor()
|
|
120
120
|
cur.execute(sql)
|
|
121
121
|
self.conn.commit()
|
|
@@ -125,38 +125,29 @@ class Model(QueryBuilder):
|
|
|
125
125
|
sql = self.__select__(self.table, ["*"], where)
|
|
126
126
|
cur = self.conn.cursor()
|
|
127
127
|
cur.execute(sql)
|
|
128
|
-
|
|
129
|
-
return
|
|
128
|
+
cols = [d[0] for d in cur.description]
|
|
129
|
+
return [dict(zip(cols, row)) for row in cur.fetchall()]
|
|
130
130
|
|
|
131
131
|
def first(self, where):
|
|
132
132
|
sql = self.__select__(self.table, ["*"], where)
|
|
133
133
|
cur = self.conn.cursor()
|
|
134
134
|
cur.execute(sql)
|
|
135
|
+
cols = [d[0] for d in cur.description]
|
|
135
136
|
row = cur.fetchone()
|
|
136
|
-
return row
|
|
137
|
+
return dict(zip(cols, row)) if row else None
|
|
137
138
|
|
|
138
139
|
class ORM:
|
|
139
|
-
|
|
140
|
-
__models__ = {}
|
|
141
|
-
__instance__ = None
|
|
142
140
|
|
|
143
|
-
|
|
144
|
-
def instance(filename, password, salt, schema):
|
|
145
|
-
if ORM.__instance__ == None:
|
|
146
|
-
ORM.__instance__ = ORM(filename, password, salt, schema)
|
|
147
|
-
return ORM.__instance__
|
|
141
|
+
__models__ = {}
|
|
148
142
|
|
|
149
143
|
def __init__(self, filename, password, salt, schema):
|
|
150
144
|
|
|
151
145
|
self.filename = filename
|
|
152
146
|
self.password = password
|
|
153
147
|
self.salt = salt
|
|
154
|
-
self.__instance__ = self
|
|
155
148
|
|
|
156
|
-
install =
|
|
157
|
-
|
|
158
|
-
install = True
|
|
159
|
-
|
|
149
|
+
install = not os.path.exists(filename)
|
|
150
|
+
|
|
160
151
|
self.conn = open_cdb(self.filename, self.password, self.salt)
|
|
161
152
|
|
|
162
153
|
for table in schema:
|
|
@@ -170,6 +161,6 @@ class ORM:
|
|
|
170
161
|
if name in self.__models__:
|
|
171
162
|
return self.__models__[name]
|
|
172
163
|
return None
|
|
173
|
-
|
|
164
|
+
|
|
174
165
|
def save(self):
|
|
175
166
|
save_cdb(self.conn, self.filename, self.password, self.salt)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
import tempfile
|
|
6
|
+
|
|
7
|
+
from pyorm import ORM, load_config
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
SCHEMA = {
|
|
11
|
+
"users": {
|
|
12
|
+
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
|
|
13
|
+
"name": "TEXT NOT NULL",
|
|
14
|
+
"email": "TEXT NOT NULL",
|
|
15
|
+
"age": "INT NOT NULL",
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def run_pyorm_init(workdir):
|
|
21
|
+
subprocess.run(
|
|
22
|
+
[sys.executable, "-m", "pyorm.cli", "--init", "1"],
|
|
23
|
+
cwd=workdir,
|
|
24
|
+
check=True,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_init_creates_config_file():
|
|
29
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
30
|
+
run_pyorm_init(tmp)
|
|
31
|
+
|
|
32
|
+
config_path = os.path.join(tmp, ".pyorm")
|
|
33
|
+
assert os.path.exists(config_path), ".pyorm config file was not created"
|
|
34
|
+
|
|
35
|
+
with open(config_path) as f:
|
|
36
|
+
raw = json.load(f)
|
|
37
|
+
assert "SALT" in raw and "PASSWORD" in raw
|
|
38
|
+
|
|
39
|
+
cnf = load_config(config_path)
|
|
40
|
+
assert isinstance(cnf["SALT"], bytes) and len(cnf["SALT"]) == 16
|
|
41
|
+
assert isinstance(cnf["PASSWORD"], bytes) and len(cnf["PASSWORD"]) > 0
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_crud_roundtrip():
|
|
45
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
46
|
+
run_pyorm_init(tmp)
|
|
47
|
+
cnf = load_config(os.path.join(tmp, ".pyorm"))
|
|
48
|
+
db_path = os.path.join(tmp, "users.db")
|
|
49
|
+
|
|
50
|
+
orm = ORM(db_path, cnf["PASSWORD"], cnf["SALT"], SCHEMA)
|
|
51
|
+
users = orm.model("users")
|
|
52
|
+
assert users is not None
|
|
53
|
+
|
|
54
|
+
alice_id = users.insert({"name": "Alice", "email": "alice@example.com", "age": 30})
|
|
55
|
+
bob_id = users.insert({"name": "Bob", "email": "bob@example.com", "age": 42})
|
|
56
|
+
assert alice_id == 1 and bob_id == 2
|
|
57
|
+
|
|
58
|
+
rows = users.find()
|
|
59
|
+
assert len(rows) == 2
|
|
60
|
+
|
|
61
|
+
updated = users.update({"id": alice_id}, {"age": 31})
|
|
62
|
+
assert updated == 1
|
|
63
|
+
|
|
64
|
+
alice = users.first({"id": alice_id})
|
|
65
|
+
assert alice["name"] == "Alice" and alice["age"] == 31
|
|
66
|
+
|
|
67
|
+
deleted = users.delete({"id": bob_id})
|
|
68
|
+
assert deleted == 1
|
|
69
|
+
assert len(users.find()) == 1
|
|
70
|
+
|
|
71
|
+
orm.save()
|
|
72
|
+
assert os.path.exists(db_path), "encrypted db file was not written"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_persistence_across_instances():
|
|
76
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
77
|
+
run_pyorm_init(tmp)
|
|
78
|
+
cnf = load_config(os.path.join(tmp, ".pyorm"))
|
|
79
|
+
db_path = os.path.join(tmp, "persist.db")
|
|
80
|
+
|
|
81
|
+
ORM.__models__ = {}
|
|
82
|
+
orm = ORM(db_path, cnf["PASSWORD"], cnf["SALT"], SCHEMA)
|
|
83
|
+
orm.model("users").insert({"name": "Carol", "email": "carol@example.com", "age": 25})
|
|
84
|
+
orm.save()
|
|
85
|
+
|
|
86
|
+
ORM.__models__ = {}
|
|
87
|
+
orm2 = ORM(db_path, cnf["PASSWORD"], cnf["SALT"], SCHEMA)
|
|
88
|
+
rows = orm2.model("users").find()
|
|
89
|
+
assert len(rows) == 1
|
|
90
|
+
assert rows[0]["name"] == "Carol"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if __name__ == "__main__":
|
|
94
|
+
test_init_creates_config_file()
|
|
95
|
+
print("init test: ok")
|
|
96
|
+
test_crud_roundtrip()
|
|
97
|
+
print("crud test: ok")
|
|
98
|
+
test_persistence_across_instances()
|
|
99
|
+
print("persistence test: ok")
|
PyCyphORM-0.1.3/PKG-INFO
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: PyCyphORM
|
|
3
|
-
Version: 0.1.3
|
|
4
|
-
Summary: A Minimalistic SQLite InMemory Encrypted ORM
|
|
5
|
-
Author: jafrmartins
|
|
6
|
-
Author-email: j.afr.martins@outlook.pt
|
|
7
|
-
Keywords: sqlite encrypted inmemory orm
|
|
8
|
-
Description-Content-Type: text/markdown
|
|
9
|
-
|
|
10
|
-
# PyCyphOrm
|
|
11
|
-
|
|
12
|
-
A Minimalistic SQLite InMemory Encrypted ORM
|
|
13
|
-
|
|
14
|
-
## Usage
|
|
15
|
-
|
|
16
|
-
### Command Line Interface
|
|
17
|
-
|
|
18
|
-
```sh
|
|
19
|
-
usage: PyCyphORM [-h] [-i INIT] [-d FILEPATH]
|
|
20
|
-
|
|
21
|
-
A Minimalistic SQLite InMemory Encrypted ORM
|
|
22
|
-
|
|
23
|
-
options:
|
|
24
|
-
-h, --help show this help message and exit
|
|
25
|
-
-i INIT, --init INIT Initialize Salt and Password for
|
|
26
|
-
Encrypted Database
|
|
27
|
-
-d FILEPATH, --decrypt FILEPATH
|
|
28
|
-
Descrypt SQLite Database
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Example
|
|
32
|
-
|
|
33
|
-
```python
|
|
34
|
-
|
|
35
|
-
from PyCyphORM.lib import load_config, ORM
|
|
36
|
-
|
|
37
|
-
cnf = load_config(".pyorm")
|
|
38
|
-
orm = ORM.instance(".cache", cnf["PASSWORD"], cnf["SALT"], {
|
|
39
|
-
"Note": {
|
|
40
|
-
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
|
|
41
|
-
"title": "TEXT NOT NULL",
|
|
42
|
-
"description": "TEXT NOT NULL",
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
orm.model("Note").insert({
|
|
48
|
-
"title": "Your Title #1",
|
|
49
|
-
"description": "Your Descriptioj #2",
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
orm.save()
|
|
53
|
-
|
|
54
|
-
```
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: PyCyphORM
|
|
3
|
-
Version: 0.1.3
|
|
4
|
-
Summary: A Minimalistic SQLite InMemory Encrypted ORM
|
|
5
|
-
Author: jafrmartins
|
|
6
|
-
Author-email: j.afr.martins@outlook.pt
|
|
7
|
-
Keywords: sqlite encrypted inmemory orm
|
|
8
|
-
Description-Content-Type: text/markdown
|
|
9
|
-
|
|
10
|
-
# PyCyphOrm
|
|
11
|
-
|
|
12
|
-
A Minimalistic SQLite InMemory Encrypted ORM
|
|
13
|
-
|
|
14
|
-
## Usage
|
|
15
|
-
|
|
16
|
-
### Command Line Interface
|
|
17
|
-
|
|
18
|
-
```sh
|
|
19
|
-
usage: PyCyphORM [-h] [-i INIT] [-d FILEPATH]
|
|
20
|
-
|
|
21
|
-
A Minimalistic SQLite InMemory Encrypted ORM
|
|
22
|
-
|
|
23
|
-
options:
|
|
24
|
-
-h, --help show this help message and exit
|
|
25
|
-
-i INIT, --init INIT Initialize Salt and Password for
|
|
26
|
-
Encrypted Database
|
|
27
|
-
-d FILEPATH, --decrypt FILEPATH
|
|
28
|
-
Descrypt SQLite Database
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Example
|
|
32
|
-
|
|
33
|
-
```python
|
|
34
|
-
|
|
35
|
-
from PyCyphORM.lib import load_config, ORM
|
|
36
|
-
|
|
37
|
-
cnf = load_config(".pyorm")
|
|
38
|
-
orm = ORM.instance(".cache", cnf["PASSWORD"], cnf["SALT"], {
|
|
39
|
-
"Note": {
|
|
40
|
-
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
|
|
41
|
-
"title": "TEXT NOT NULL",
|
|
42
|
-
"description": "TEXT NOT NULL",
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
orm.model("Note").insert({
|
|
48
|
-
"title": "Your Title #1",
|
|
49
|
-
"description": "Your Descriptioj #2",
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
orm.save()
|
|
53
|
-
|
|
54
|
-
```
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
README.md
|
|
2
|
-
setup.py
|
|
3
|
-
PyCyphORM.egg-info/PKG-INFO
|
|
4
|
-
PyCyphORM.egg-info/SOURCES.txt
|
|
5
|
-
PyCyphORM.egg-info/dependency_links.txt
|
|
6
|
-
PyCyphORM.egg-info/entry_points.txt
|
|
7
|
-
PyCyphORM.egg-info/top_level.txt
|
|
8
|
-
src/PyCyphORM/__init__.py
|
|
9
|
-
src/PyCyphORM/cli.py
|
|
10
|
-
src/PyCyphORM/lib/__init__.py
|
|
11
|
-
src/PyCyphORM/lib/adapter.py
|
|
12
|
-
src/PyCyphORM/lib/orm.py
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
PyCyphORM
|
PyCyphORM-0.1.3/README.md
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# PyCyphOrm
|
|
2
|
-
|
|
3
|
-
A Minimalistic SQLite InMemory Encrypted ORM
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
### Command Line Interface
|
|
8
|
-
|
|
9
|
-
```sh
|
|
10
|
-
usage: PyCyphORM [-h] [-i INIT] [-d FILEPATH]
|
|
11
|
-
|
|
12
|
-
A Minimalistic SQLite InMemory Encrypted ORM
|
|
13
|
-
|
|
14
|
-
options:
|
|
15
|
-
-h, --help show this help message and exit
|
|
16
|
-
-i INIT, --init INIT Initialize Salt and Password for
|
|
17
|
-
Encrypted Database
|
|
18
|
-
-d FILEPATH, --decrypt FILEPATH
|
|
19
|
-
Descrypt SQLite Database
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### Example
|
|
23
|
-
|
|
24
|
-
```python
|
|
25
|
-
|
|
26
|
-
from PyCyphORM.lib import load_config, ORM
|
|
27
|
-
|
|
28
|
-
cnf = load_config(".pyorm")
|
|
29
|
-
orm = ORM.instance(".cache", cnf["PASSWORD"], cnf["SALT"], {
|
|
30
|
-
"Note": {
|
|
31
|
-
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
|
|
32
|
-
"title": "TEXT NOT NULL",
|
|
33
|
-
"description": "TEXT NOT NULL",
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
orm.model("Note").insert({
|
|
39
|
-
"title": "Your Title #1",
|
|
40
|
-
"description": "Your Descriptioj #2",
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
orm.save()
|
|
44
|
-
|
|
45
|
-
```
|
PyCyphORM-0.1.3/setup.py
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import setuptools
|
|
3
|
-
|
|
4
|
-
# pip install ./PyORM --upgrade -t /home/jam/.local/lib/python3.10/site-packages/PyORM
|
|
5
|
-
|
|
6
|
-
readme = open("%s%sREADME.md"%(os.path.dirname(__file__), os.path.sep)).read()
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
setuptools.setup(
|
|
10
|
-
name='PyCyphORM',
|
|
11
|
-
version='0.1.3',
|
|
12
|
-
author='jafrmartins',
|
|
13
|
-
keywords='sqlite encrypted inmemory orm',
|
|
14
|
-
author_email='j.afr.martins@outlook.pt',
|
|
15
|
-
description='A Minimalistic SQLite InMemory Encrypted ORM',
|
|
16
|
-
packages=setuptools.find_packages('src'),
|
|
17
|
-
install_requires=[],
|
|
18
|
-
package_dir={'PyCyphORM': 'src/PyCyphORM', },
|
|
19
|
-
entry_points={
|
|
20
|
-
'console_scripts': [
|
|
21
|
-
'pycyphorm=cli:cli',
|
|
22
|
-
],
|
|
23
|
-
},
|
|
24
|
-
include_package_data=True,
|
|
25
|
-
long_description=readme,
|
|
26
|
-
long_description_content_type='text/markdown'
|
|
27
|
-
)
|
|
File without changes
|
|
File without changes
|