1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
|
import json
import os
import random
import tempfile
import pytest
from tinydb import TinyDB, where
from tinydb.storages import JSONStorage, MemoryStorage, Storage, touch
from tinydb.table import Document
random.seed()
doc = {'none': [None, None], 'int': 42, 'float': 3.1415899999999999,
'list': ['LITE', 'RES_ACID', 'SUS_DEXT'],
'dict': {'hp': 13, 'sp': 5},
'bool': [True, False, True, False]}
def test_json(tmpdir):
# Write contents
path = str(tmpdir.join('test.db'))
storage = JSONStorage(path)
storage.write(doc)
# Verify contents
assert doc == storage.read()
storage.close()
def test_json_kwargs(tmpdir):
db_file = tmpdir.join('test.db')
db = TinyDB(str(db_file), sort_keys=True, indent=4, separators=(',', ': '))
# Write contents
db.insert({'b': 1})
db.insert({'a': 1})
assert db_file.read() == '''{
"_default": {
"1": {
"b": 1
},
"2": {
"a": 1
}
}
}'''
db.close()
def test_json_readwrite(tmpdir):
"""
Regression test for issue #1
"""
path = str(tmpdir.join('test.db'))
# Create TinyDB instance
db = TinyDB(path, storage=JSONStorage)
item = {'name': 'A very long entry'}
item2 = {'name': 'A short one'}
def get(s):
return db.get(where('name') == s)
db.insert(item)
assert get('A very long entry') == item
db.remove(where('name') == 'A very long entry')
assert get('A very long entry') is None
db.insert(item2)
assert get('A short one') == item2
db.remove(where('name') == 'A short one')
assert get('A short one') is None
db.close()
def test_json_read(tmpdir):
r"""Open a database only for reading"""
path = str(tmpdir.join('test.db'))
with pytest.raises(FileNotFoundError):
db = TinyDB(path, storage=JSONStorage, access_mode='r')
# Create small database
db = TinyDB(path, storage=JSONStorage)
db.insert({'b': 1})
db.insert({'a': 1})
db.close()
# Access in read mode
db = TinyDB(path, storage=JSONStorage, access_mode='r')
assert db.get(where('a') == 1) == {'a': 1} # reading is fine
with pytest.raises(IOError):
db.insert({'c': 1}) # writing is not
db.close()
def test_create_dirs():
temp_dir = tempfile.gettempdir()
while True:
dname = os.path.join(temp_dir, str(random.getrandbits(20)))
if not os.path.exists(dname):
db_dir = dname
db_file = os.path.join(db_dir, 'db.json')
break
with pytest.raises(IOError):
JSONStorage(db_file)
JSONStorage(db_file, create_dirs=True).close()
assert os.path.exists(db_file)
# Use create_dirs with already existing directory
JSONStorage(db_file, create_dirs=True).close()
assert os.path.exists(db_file)
os.remove(db_file)
os.rmdir(db_dir)
def test_json_invalid_directory():
with pytest.raises(IOError):
with TinyDB('/this/is/an/invalid/path/db.json', storage=JSONStorage):
pass
def test_in_memory():
# Write contents
storage = MemoryStorage()
storage.write(doc)
# Verify contents
assert doc == storage.read()
# Test case for #21
other = MemoryStorage()
other.write({})
assert other.read() != storage.read()
def test_in_memory_close():
with TinyDB(storage=MemoryStorage) as db:
db.insert({})
def test_custom():
# noinspection PyAbstractClass
class MyStorage(Storage):
pass
with pytest.raises(TypeError):
MyStorage()
def test_read_once():
count = 0
# noinspection PyAbstractClass
class MyStorage(Storage):
def __init__(self):
self.memory = None
def read(self):
nonlocal count
count += 1
return self.memory
def write(self, data):
self.memory = data
with TinyDB(storage=MyStorage) as db:
assert count == 0
db.table(db.default_table_name)
assert count == 0
db.all()
assert count == 1
db.insert({'foo': 'bar'})
assert count == 3 # One for getting the next ID, one for the insert
db.all()
assert count == 4
def test_custom_with_exception():
class MyStorage(Storage):
def read(self):
pass
def write(self, data):
pass
def __init__(self):
raise ValueError()
def close(self):
raise RuntimeError()
with pytest.raises(ValueError):
with TinyDB(storage=MyStorage) as db:
pass
def test_yaml(tmpdir):
"""
:type tmpdir: py._path.local.LocalPath
"""
try:
import yaml
except ImportError:
return pytest.skip('PyYAML not installed')
def represent_doc(dumper, data):
# Represent `Document` objects as their dict's string representation
# which PyYAML understands
return dumper.represent_data(dict(data))
yaml.add_representer(Document, represent_doc)
class YAMLStorage(Storage):
def __init__(self, filename):
self.filename = filename
touch(filename, False)
def read(self):
with open(self.filename) as handle:
data = yaml.safe_load(handle.read())
return data
def write(self, data):
with open(self.filename, 'w') as handle:
yaml.dump(data, handle)
def close(self):
pass
# Write contents
path = str(tmpdir.join('test.db'))
db = TinyDB(path, storage=YAMLStorage)
db.insert(doc)
assert db.all() == [doc]
db.update({'name': 'foo'})
assert '!' not in tmpdir.join('test.db').read()
assert db.contains(where('name') == 'foo')
assert len(db) == 1
def test_encoding(tmpdir):
japanese_doc = {"Test": u"こんにちは世界"}
path = str(tmpdir.join('test.db'))
# cp936 is used for japanese encodings
jap_storage = JSONStorage(path, encoding="cp936")
jap_storage.write(japanese_doc)
try:
exception = json.decoder.JSONDecodeError
except AttributeError:
exception = ValueError
with pytest.raises(exception):
# cp037 is used for english encodings
eng_storage = JSONStorage(path, encoding="cp037")
eng_storage.read()
jap_storage = JSONStorage(path, encoding="cp936")
assert japanese_doc == jap_storage.read()
|