klongpy 0.6.8__py3-none-any.whl → 0.7.0__py3-none-any.whl
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.
- klongpy/__init__.py +19 -1
- klongpy/adverbs.py +5 -5
- klongpy/autograd.py +308 -0
- klongpy/backend.py +167 -99
- klongpy/backends/__init__.py +94 -0
- klongpy/backends/base.py +320 -0
- klongpy/backends/numpy_backend.py +122 -0
- klongpy/backends/torch_backend.py +995 -0
- klongpy-0.6.8.data/scripts/kgpy → klongpy/cli.py +65 -88
- klongpy/core.py +228 -106
- klongpy/db/sys_fn_db.py +4 -3
- klongpy/dyads.py +173 -32
- klongpy/interpreter.py +31 -3
- klongpy/lib/help.kg +2 -2
- klongpy/monads.py +49 -12
- klongpy/repl.py +91 -0
- klongpy/sys_fn.py +129 -18
- klongpy/sys_fn_autograd.py +290 -0
- klongpy/sys_fn_ipc.py +18 -7
- klongpy/sys_fn_timer.py +13 -3
- klongpy/web/sys_fn_web.py +28 -6
- klongpy-0.7.0.dist-info/METADATA +493 -0
- klongpy-0.7.0.dist-info/RECORD +48 -0
- {klongpy-0.6.8.dist-info → klongpy-0.7.0.dist-info}/WHEEL +1 -1
- klongpy-0.7.0.dist-info/entry_points.txt +2 -0
- {klongpy-0.6.8.dist-info → klongpy-0.7.0.dist-info}/top_level.txt +0 -1
- klongpy-0.6.8.dist-info/METADATA +0 -412
- klongpy-0.6.8.dist-info/RECORD +0 -72
- tests/__init__.py +0 -6
- tests/gen_join_over.py +0 -119
- tests/gen_py_suite.py +0 -77
- tests/gen_test_fn.py +0 -259
- tests/perf_async.py +0 -25
- tests/perf_avg.py +0 -18
- tests/perf_duckdb.py +0 -32
- tests/perf_gen.py +0 -38
- tests/perf_ipc_overhead.py +0 -34
- tests/perf_join.py +0 -53
- tests/perf_load.py +0 -17
- tests/perf_prog.py +0 -18
- tests/perf_serdes.py +0 -52
- tests/perf_sys_fn_db.py +0 -263
- tests/perf_vector.py +0 -40
- tests/test_accel.py +0 -227
- tests/test_df_cache.py +0 -85
- tests/test_examples.py +0 -64
- tests/test_extra_suite.py +0 -382
- tests/test_file_cache.py +0 -185
- tests/test_interop.py +0 -181
- tests/test_kgtests.py +0 -65
- tests/test_known_bugs.py +0 -206
- tests/test_prog.py +0 -107
- tests/test_suite.py +0 -1479
- tests/test_suite_file.py +0 -153
- tests/test_sys_fn.py +0 -420
- tests/test_sys_fn_db.py +0 -88
- tests/test_sys_fn_ipc.py +0 -587
- tests/test_sys_fn_timer.py +0 -133
- tests/test_util.py +0 -233
- tests/utils.py +0 -126
- {klongpy-0.6.8.dist-info → klongpy-0.7.0.dist-info/licenses}/LICENSE +0 -0
tests/test_extra_suite.py
DELETED
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
|
|
3
|
-
from utils import *
|
|
4
|
-
|
|
5
|
-
from klongpy import KlongInterpreter
|
|
6
|
-
from klongpy.core import (KGChar, KGSym, is_float, is_integer, rec_flatten)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# add tests not included in the original kg suite
|
|
10
|
-
class TestExtraCoreSuite(unittest.TestCase):
|
|
11
|
-
|
|
12
|
-
def assert_eval_cmp(self, a, b, klong=None):
|
|
13
|
-
self.assertTrue(eval_cmp(a, b, klong=klong))
|
|
14
|
-
|
|
15
|
-
def test_negate_array_result_type(self):
|
|
16
|
-
""" ensure the result type of negating an array is correct """
|
|
17
|
-
klong = KlongInterpreter()
|
|
18
|
-
r = klong("-1]")
|
|
19
|
-
self.assertTrue(is_integer(r))
|
|
20
|
-
r = klong("-1.0]")
|
|
21
|
-
self.assertTrue(is_float(r))
|
|
22
|
-
r = klong("-[1 2 3]")
|
|
23
|
-
self.assertTrue(r.dtype == int)
|
|
24
|
-
r = klong("-[1.0 2.0 3.0]")
|
|
25
|
-
self.assertTrue(r.dtype == float)
|
|
26
|
-
|
|
27
|
-
def test_match_empty_array_to_undefined_symbol(self):
|
|
28
|
-
""" symbol is undefined so does not match the empty array """
|
|
29
|
-
klong = KlongInterpreter()
|
|
30
|
-
r = klong('[]~.a')
|
|
31
|
-
self.assertEqual(r, 0)
|
|
32
|
-
|
|
33
|
-
def test_vectorized(self):
|
|
34
|
-
klong = KlongInterpreter()
|
|
35
|
-
r = klong("2*!1000")
|
|
36
|
-
self.assertTrue(kg_equal(r, np.arange(1000)*2))
|
|
37
|
-
|
|
38
|
-
# This is different behavior than Klong, which doesn't allow at/index on dictionaries.
|
|
39
|
-
def test_dict_at_index(self):
|
|
40
|
-
klong = KlongInterpreter()
|
|
41
|
-
klong("D:::{[1 2]}")
|
|
42
|
-
r = klong("D@1")
|
|
43
|
-
self.assertEqual(r, 2)
|
|
44
|
-
with self.assertRaises(KeyError):
|
|
45
|
-
klong("D@2")
|
|
46
|
-
|
|
47
|
-
def test_each_dict_with_mixed_types(self):
|
|
48
|
-
klong = KlongInterpreter()
|
|
49
|
-
klong["D"] = {object: [1, 2, 3]}
|
|
50
|
-
klong(".p'D")
|
|
51
|
-
|
|
52
|
-
def test_apply_range(self):
|
|
53
|
-
klong = KlongInterpreter()
|
|
54
|
-
r = klong("{x}@,!100")
|
|
55
|
-
self.assertTrue(kg_equal(r, np.arange(100)))
|
|
56
|
-
klong("avg::{(+/x)%#x}")
|
|
57
|
-
r = klong("avg@,!100")
|
|
58
|
-
self.assertEqual(r,49.5)
|
|
59
|
-
|
|
60
|
-
def test_eval_quote_string(self):
|
|
61
|
-
klong = KlongInterpreter()
|
|
62
|
-
r = klong(':"hello"')
|
|
63
|
-
self.assertTrue(r is None)
|
|
64
|
-
|
|
65
|
-
def test_array_identity(self):
|
|
66
|
-
klong = KlongInterpreter()
|
|
67
|
-
r = klong('[]')
|
|
68
|
-
self.assertTrue(kg_equal(r, np.array([],dtype=object)))
|
|
69
|
-
r = klong('[1]')
|
|
70
|
-
self.assertTrue(kg_equal(r, np.array([1],dtype=object)))
|
|
71
|
-
r = klong('[[1]]')
|
|
72
|
-
self.assertTrue(kg_equal(r, np.array([[1]],dtype=object)))
|
|
73
|
-
r = klong('[[1] [2]]')
|
|
74
|
-
self.assertTrue(kg_equal(r, np.array([[1],[2]],dtype=object)))
|
|
75
|
-
r = klong('[[1] [2 3]]')
|
|
76
|
-
self.assertTrue(kg_equal(r, np.array([[1],[2,3]],dtype=object)))
|
|
77
|
-
r = klong('[[[1]] [2 3]]')
|
|
78
|
-
self.assertTrue(kg_equal(r, np.array([[[1]],[2,3]],dtype=object)))
|
|
79
|
-
r = klong('[[1] [[2 3]]]')
|
|
80
|
-
self.assertTrue(kg_equal(r, np.array([[1],[[2,3]]],dtype=object)))
|
|
81
|
-
r = klong('[[[1]] [[2 3]]]')
|
|
82
|
-
self.assertTrue(kg_equal(r, np.array([[[1]],[[2,3]]],dtype=object)))
|
|
83
|
-
|
|
84
|
-
def test_jagged_array_identity(self):
|
|
85
|
-
klong = KlongInterpreter()
|
|
86
|
-
r = klong('[[0] [[1]]]')
|
|
87
|
-
q = np.array([[0],[[1]]],dtype=object)
|
|
88
|
-
self.assertTrue(kg_equal(r, q))
|
|
89
|
-
|
|
90
|
-
def test_match_array(self):
|
|
91
|
-
klong = KlongInterpreter()
|
|
92
|
-
r = klong('(^[1])~0')
|
|
93
|
-
self.assertFalse(r is False)
|
|
94
|
-
self.assertEqual(r,0)
|
|
95
|
-
|
|
96
|
-
def test_prime(self):
|
|
97
|
-
klong = KlongInterpreter()
|
|
98
|
-
klong('prime::{&/x!:\\2+!_x^1%2}') # note \\ ==> \
|
|
99
|
-
r = klong("prime(251)")
|
|
100
|
-
self.assertTrue(is_integer(r))
|
|
101
|
-
self.assertEqual(r, 1)
|
|
102
|
-
|
|
103
|
-
def test_floor_as_int(self):
|
|
104
|
-
klong = KlongInterpreter()
|
|
105
|
-
r = klong('_30%2')
|
|
106
|
-
self.assertTrue(is_integer(r))
|
|
107
|
-
self.assertEqual(r, 15)
|
|
108
|
-
r = klong('_[30 20]%2')
|
|
109
|
-
for x in r:
|
|
110
|
-
self.assertTrue(is_integer(x))
|
|
111
|
-
self.assertTrue(kg_equal(r, [15, 10]))
|
|
112
|
-
|
|
113
|
-
def test_drop_string(self):
|
|
114
|
-
klong = KlongInterpreter()
|
|
115
|
-
klong("""
|
|
116
|
-
NAMES:::{}
|
|
117
|
-
AN::{[k n g];.p(x);k::(x?",")@0;n::.rs(k#x);g::.rs((k+1)_x);NAMES,n,,g}")
|
|
118
|
-
""")
|
|
119
|
-
r = klong('S::\"""John"",""boy""\"')
|
|
120
|
-
self.assertEqual(r,'"John","boy"')
|
|
121
|
-
r = klong('AN(S);NAMES')
|
|
122
|
-
self.assertEqual(r['John'], "boy")
|
|
123
|
-
|
|
124
|
-
# read 123456 from "123456 hello" requires parsing by space
|
|
125
|
-
def test_read_number_from_various_strings(self):
|
|
126
|
-
klong = KlongInterpreter()
|
|
127
|
-
# DIFF: Klong will puke on this with undefined
|
|
128
|
-
r = klong('.rs("123456 hello")')
|
|
129
|
-
self.assertEqual(r, 123456)
|
|
130
|
-
|
|
131
|
-
def test_join_nested_arrays(self):
|
|
132
|
-
self.assert_eval_cmp('[[0 0] [1 1]],,2,2', '[[0 0] [1 1] [2 2]]')
|
|
133
|
-
|
|
134
|
-
def test_range_over_nested_arrays(self):
|
|
135
|
-
self.assert_eval_cmp('?[[0 0] [1 1] 3 3]', '[[0 0] [1 1] 3]')
|
|
136
|
-
self.assert_eval_cmp('?[[0 0] [1 1] [1 1]]', '[[0 0] [1 1]]')
|
|
137
|
-
self.assert_eval_cmp('?[[0 0] [1 1] [1 1] 3 3]', '[[0 0] [1 1] 3]')
|
|
138
|
-
self.assert_eval_cmp('?[[[0 0] [0 0] [1 1]] [1 1] [1 1]]', '[[[0 0] [0 0] [1 1]] [1 1]]')
|
|
139
|
-
self.assert_eval_cmp('?[[[0 0] [0 0] [1 1]] [1 1] [1 1] 3 3]', '[[[0 0] [0 0] [1 1]] [1 1] 3]')
|
|
140
|
-
self.assert_eval_cmp('?[[0 0] [1 0] [2 0] [3 0] [4 1] [4 2] [4 3] [3 4] [2 4] [3 3] [4 3] [3 2] [2 2] [1 2]]', '[[0 0] [1 0] [2 0] [3 0] [4 1] [4 2] [4 3] [3 4] [2 4] [3 3] [3 2] [2 2] [1 2]]')
|
|
141
|
-
|
|
142
|
-
def test_sum_over_nested_arrays(self):
|
|
143
|
-
"""
|
|
144
|
-
sum over nested arrays should reduce
|
|
145
|
-
"""
|
|
146
|
-
self.assert_eval_cmp('+/[1 2 3]', '6')
|
|
147
|
-
self.assert_eval_cmp('+/[[1 2 3]]', '[1 2 3]')
|
|
148
|
-
self.assert_eval_cmp('+/[[1 2 3] [4 5 6]]', '[5 7 9]')
|
|
149
|
-
self.assert_eval_cmp('+/[[1 2 3] [4 5 6] [7 8 9]]', '[12 15 18]')
|
|
150
|
-
|
|
151
|
-
def test_power_preserve_type(self):
|
|
152
|
-
klong = KlongInterpreter()
|
|
153
|
-
r = klong("10^5")
|
|
154
|
-
self.assertTrue(is_integer(r))
|
|
155
|
-
r = klong("10.5^5")
|
|
156
|
-
self.assertTrue(is_float(r))
|
|
157
|
-
|
|
158
|
-
def test_join_array_dict(self):
|
|
159
|
-
klong = KlongInterpreter()
|
|
160
|
-
klong("""
|
|
161
|
-
N::{d:::{[:s 0] [:c []]};d,:p,x;d,:n,y}
|
|
162
|
-
D::N(1%0;"/")
|
|
163
|
-
n::N(D;"x")
|
|
164
|
-
""")
|
|
165
|
-
klong('(D?:c),n')
|
|
166
|
-
|
|
167
|
-
def test_join_sym_string(self):
|
|
168
|
-
klong = KlongInterpreter()
|
|
169
|
-
r = klong(':p,"hello"')
|
|
170
|
-
self.assertTrue(isinstance(r[0],KGSym))
|
|
171
|
-
self.assertEqual(r[1],"hello")
|
|
172
|
-
|
|
173
|
-
def test_join_sym_dict(self):
|
|
174
|
-
klong = KlongInterpreter()
|
|
175
|
-
klong("D:::{[1 2]}")
|
|
176
|
-
r = klong(":p,D")
|
|
177
|
-
self.assertTrue(isinstance(r[0],KGSym))
|
|
178
|
-
self.assertTrue(isinstance(r[1],dict))
|
|
179
|
-
|
|
180
|
-
def test_complex_join_dict_create(self):
|
|
181
|
-
klong = KlongInterpreter()
|
|
182
|
-
klong("""
|
|
183
|
-
N::{d:::{[:s 0] [:c []]};d,:p,x;d,:n,y}
|
|
184
|
-
D::N(1%0;"/")
|
|
185
|
-
""")
|
|
186
|
-
r = klong('q::N(D;"hello")')
|
|
187
|
-
self.assertEqual(klong("q?:s"), 0)
|
|
188
|
-
self.assertTrue(kg_equal(klong("q?:c"), []))
|
|
189
|
-
self.assertEqual(klong("q?:n"), "hello")
|
|
190
|
-
self.assertTrue(isinstance(klong("q?:p"), dict))
|
|
191
|
-
|
|
192
|
-
def test_join_sym_int(self):
|
|
193
|
-
klong = KlongInterpreter()
|
|
194
|
-
r = klong(":p,43")
|
|
195
|
-
self.assertTrue(isinstance(r[0],KGSym))
|
|
196
|
-
self.assertTrue(isinstance(r[1],int))
|
|
197
|
-
|
|
198
|
-
def test_integer_divide_clamp_to_int(self):
|
|
199
|
-
klong = KlongInterpreter()
|
|
200
|
-
r = klong("24:%2")
|
|
201
|
-
self.assertTrue(is_integer(r))
|
|
202
|
-
r = klong("[12 24]:%2")
|
|
203
|
-
self.assertTrue(is_integer(r[0]))
|
|
204
|
-
self.assertTrue(is_integer(r[1]))
|
|
205
|
-
|
|
206
|
-
def test_enumerate_float(self):
|
|
207
|
-
klong = KlongInterpreter()
|
|
208
|
-
with self.assertRaises(RuntimeError):
|
|
209
|
-
klong("!(24%2)")
|
|
210
|
-
r = klong("!(24:%2)")
|
|
211
|
-
self.assertEqual(len(r), 12)
|
|
212
|
-
|
|
213
|
-
def test_at_index_single_index(self):
|
|
214
|
-
klong = KlongInterpreter()
|
|
215
|
-
def _char_test(x):
|
|
216
|
-
if not isinstance(x,KGChar):
|
|
217
|
-
raise RuntimeError("should be char")
|
|
218
|
-
klong['ischar'] = _char_test
|
|
219
|
-
klong('ischar("hello"@2)')
|
|
220
|
-
|
|
221
|
-
def test_at_index_array_index(self):
|
|
222
|
-
klong = KlongInterpreter()
|
|
223
|
-
def _str_test(x):
|
|
224
|
-
if isinstance(x,KGChar):
|
|
225
|
-
raise RuntimeError("should be string")
|
|
226
|
-
klong['isstr'] = _str_test
|
|
227
|
-
klong('isstr("hello"@[2])')
|
|
228
|
-
klong('isstr("hello"@[1 2 2])')
|
|
229
|
-
|
|
230
|
-
def test_module_fallback(self):
|
|
231
|
-
klong = KlongInterpreter()
|
|
232
|
-
r = klong("""
|
|
233
|
-
pi::3.14
|
|
234
|
-
.module(:test)
|
|
235
|
-
foo::pi
|
|
236
|
-
.module(0)
|
|
237
|
-
foo
|
|
238
|
-
""")
|
|
239
|
-
self.assertTrue(r,3.14)
|
|
240
|
-
|
|
241
|
-
def test_read_enotation(self):
|
|
242
|
-
klong = KlongInterpreter()
|
|
243
|
-
r = klong('t::1.0e8;')
|
|
244
|
-
self.assertEqual(r, 1.0e8)
|
|
245
|
-
r = klong('t::1.0e-8;')
|
|
246
|
-
self.assertEqual(r, 1.0e-8)
|
|
247
|
-
|
|
248
|
-
def test_read_list(self):
|
|
249
|
-
klong = KlongInterpreter()
|
|
250
|
-
r = klong('[]')
|
|
251
|
-
self.assertTrue(kg_equal(r,[]))
|
|
252
|
-
klong = KlongInterpreter()
|
|
253
|
-
r = klong('[1 2 3 4]')
|
|
254
|
-
self.assertTrue(kg_equal(r,[1,2,3,4]))
|
|
255
|
-
klong = KlongInterpreter()
|
|
256
|
-
r = klong('[1 2 3 4 ]') # add spaces as found in suite
|
|
257
|
-
self.assertTrue(kg_equal(r,[1,2,3,4]))
|
|
258
|
-
|
|
259
|
-
def test_read_list_as_arg(self):
|
|
260
|
-
"""
|
|
261
|
-
make list span lines to test whitespace skip
|
|
262
|
-
"""
|
|
263
|
-
t = """
|
|
264
|
-
zop::{x}
|
|
265
|
-
zop([
|
|
266
|
-
["hello"]
|
|
267
|
-
])
|
|
268
|
-
"""
|
|
269
|
-
klong = KlongInterpreter()
|
|
270
|
-
klong('zap::{x}')
|
|
271
|
-
r = klong('zap([])')
|
|
272
|
-
self.assertTrue(kg_equal(r,[]))
|
|
273
|
-
r = klong(t)
|
|
274
|
-
self.assertTrue(kg_equal(r,[["hello"]]))
|
|
275
|
-
|
|
276
|
-
def test_sys_comment(self):
|
|
277
|
-
t = """.comment("end-of-comment")
|
|
278
|
-
abcdefghijklmnopqrstuvwxyz
|
|
279
|
-
ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
|
280
|
-
0123456789
|
|
281
|
-
~!@#$%^&*()_+-=`[]{}:;"'<,>.
|
|
282
|
-
end-of-comment
|
|
283
|
-
|
|
284
|
-
A::1;
|
|
285
|
-
A
|
|
286
|
-
"""
|
|
287
|
-
klong = KlongInterpreter()
|
|
288
|
-
r = klong.exec(t)
|
|
289
|
-
# verify that we are returning both A::1 and A operation results
|
|
290
|
-
self.assertTrue(kg_equal(r,[1,1]))
|
|
291
|
-
r = klong(t)
|
|
292
|
-
self.assertEqual(r, 1)
|
|
293
|
-
|
|
294
|
-
def test_eval_array(self):
|
|
295
|
-
klong = KlongInterpreter()
|
|
296
|
-
r = klong('[[[1] [2] [3]] [1 2 3]]')
|
|
297
|
-
self.assertTrue(kg_equal(r,[[[1],[2],[3]],[1,2,3]]))
|
|
298
|
-
|
|
299
|
-
def test_dot_f(self):
|
|
300
|
-
klong = KlongInterpreter()
|
|
301
|
-
klong('fr::{:[x;"hello";.f(1)]}')
|
|
302
|
-
self.assert_eval_cmp('fr(0)', '"hello"', klong=klong)
|
|
303
|
-
self.assert_eval_cmp('fr(1)', '"hello"', klong=klong)
|
|
304
|
-
klong('fr::{:[x<1;x;.f(x%2)]}')
|
|
305
|
-
self.assert_eval_cmp('fr(0)', '0', klong=klong)
|
|
306
|
-
self.assert_eval_cmp('fr(1)', '0.5', klong=klong)
|
|
307
|
-
self.assert_eval_cmp('fr(12)', '0.75', klong=klong)
|
|
308
|
-
klong("fr::{:[0=x;[];1,.f(x-1)]}")
|
|
309
|
-
self.assert_eval_cmp('fr(0)', '[]', klong=klong)
|
|
310
|
-
self.assert_eval_cmp('fr(1)', '[1]', klong=klong)
|
|
311
|
-
self.assert_eval_cmp('fr(2)', '[1 1]', klong=klong)
|
|
312
|
-
self.assert_eval_cmp('fr(3)', '[1 1 1]', klong=klong)
|
|
313
|
-
|
|
314
|
-
def test_harness(self):
|
|
315
|
-
klong = KlongInterpreter()
|
|
316
|
-
klong('err::0;')
|
|
317
|
-
klong('wl::{.w(x);.p("")}')
|
|
318
|
-
klong('fail::{err::1;.d("failed: ");.p(x);.d("expected: ");wl(z);.d("got: ");wl(y);[]}')
|
|
319
|
-
klong('t::{:[~y~z;fail(x;y;z);[]]}')
|
|
320
|
-
r = klong("err")
|
|
321
|
-
self.assertEqual(r, 0)
|
|
322
|
-
klong("A::1")
|
|
323
|
-
klong('t("A::1" ; A ; 1)')
|
|
324
|
-
r = klong("err")
|
|
325
|
-
self.assertEqual(r, 0)
|
|
326
|
-
r = klong('t("A::1" ; A ; 2)')
|
|
327
|
-
r = klong("err")
|
|
328
|
-
self.assertEqual(r, 1)
|
|
329
|
-
|
|
330
|
-
def test_vector_math(self):
|
|
331
|
-
klong = KlongInterpreter()
|
|
332
|
-
r = klong("!10000000")
|
|
333
|
-
x = np.arange(10000000)
|
|
334
|
-
self.assertTrue(np.equal(x, r).all())
|
|
335
|
-
|
|
336
|
-
r = klong("1+!10000000")
|
|
337
|
-
x = np.add(x, 1)
|
|
338
|
-
self.assertTrue(np.equal(x, r).all())
|
|
339
|
-
|
|
340
|
-
r = klong("2*1+!10000000")
|
|
341
|
-
x = np.multiply(x, 2)
|
|
342
|
-
self.assertTrue(np.equal(x, r).all())
|
|
343
|
-
|
|
344
|
-
r = klong("3%2*1+!10000000")
|
|
345
|
-
x = np.divide(3, x)
|
|
346
|
-
self.assertTrue(np.equal(x, r).all())
|
|
347
|
-
|
|
348
|
-
r = klong("10-3%2*1+!10000000")
|
|
349
|
-
x = np.subtract(10, x)
|
|
350
|
-
self.assertTrue(np.equal(x, r).all())
|
|
351
|
-
|
|
352
|
-
r = klong("(1+!10)&3")
|
|
353
|
-
x = np.minimum(np.add(np.arange(10), 1), 3)
|
|
354
|
-
self.assertTrue(np.equal(x, r).all())
|
|
355
|
-
|
|
356
|
-
r = klong("(1+!10)!5")
|
|
357
|
-
x = np.fmod(np.add(np.arange(10), 1), 5)
|
|
358
|
-
self.assertTrue(np.equal(x, r).all())
|
|
359
|
-
|
|
360
|
-
def test_converge(self):
|
|
361
|
-
klong = KlongInterpreter()
|
|
362
|
-
r = klong('{(x+2%x)%2}:~2')
|
|
363
|
-
self.assertTrue(np.isclose(r,1.41421356237309504))
|
|
364
|
-
|
|
365
|
-
def test_scan_converge(self):
|
|
366
|
-
klong = KlongInterpreter()
|
|
367
|
-
r = klong('{(x+2%x)%2}\~2')
|
|
368
|
-
e = np.asarray([2. , 1.5 , 1.41666667, 1.41421569])
|
|
369
|
-
self.assertTrue(np.isclose(r,e).all())
|
|
370
|
-
|
|
371
|
-
r = klong(',/\~["a" ["b"] "c"]')
|
|
372
|
-
e = np.asarray([["a",["b"],"c"],["a","b","c"],"abc"],dtype=object)
|
|
373
|
-
x = r
|
|
374
|
-
self.assertTrue(rec_flatten(rec_fn2(e,x, lambda a,b: a == b)).all())
|
|
375
|
-
|
|
376
|
-
def test_converge_as_fn(self):
|
|
377
|
-
klong = KlongInterpreter()
|
|
378
|
-
klong('s::{(x+2%x)%2}:~2')
|
|
379
|
-
r = klong('s')
|
|
380
|
-
self.assertTrue(np.isclose(r,1.41421356237309504))
|
|
381
|
-
r = klong('s()')
|
|
382
|
-
self.assertTrue(np.isclose(r,1.41421356237309504))
|
tests/test_file_cache.py
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import platform
|
|
3
|
-
import random
|
|
4
|
-
import tempfile
|
|
5
|
-
import threading
|
|
6
|
-
import time
|
|
7
|
-
import unittest
|
|
8
|
-
from multiprocessing.pool import ThreadPool
|
|
9
|
-
|
|
10
|
-
from klongpy.db.file_cache import FileCache
|
|
11
|
-
|
|
12
|
-
# TODO: add MacOS RAM disk
|
|
13
|
-
# hdiutil attach -nomount ram://$((2 * 1024 * 100))
|
|
14
|
-
# diskutil eraseVolume HFS+ RAMDisk /dev/disk3
|
|
15
|
-
# https://stackoverflow.com/questions/1854/how-to-identify-which-os-python-is-running-on
|
|
16
|
-
|
|
17
|
-
def gen_data():
|
|
18
|
-
return bytearray(os.urandom(random.randint(10,50)))
|
|
19
|
-
|
|
20
|
-
def gen_file(tmp_dir=None):
|
|
21
|
-
tmp_dir = tmp_dir or ("/dev/shm" if platform.system() == "Linux" else None)
|
|
22
|
-
f = tempfile.NamedTemporaryFile(delete=False, dir=tmp_dir)
|
|
23
|
-
d = gen_data()
|
|
24
|
-
f.write(d)
|
|
25
|
-
f.seek(0)
|
|
26
|
-
return f,d,len(d)
|
|
27
|
-
|
|
28
|
-
class FileCacheTests(unittest.TestCase):
|
|
29
|
-
def setUp(self):
|
|
30
|
-
self.file_contents = {i:gen_file() for i in range(10)}
|
|
31
|
-
# make cache just under capactiy to hold all 4 files to force eviction
|
|
32
|
-
self.file_cache = FileCache(max_memory=(sum([x[2] for x in self.file_contents.values()]) - 1))
|
|
33
|
-
|
|
34
|
-
def test_get_file(self):
|
|
35
|
-
info = self.file_contents[0]
|
|
36
|
-
contents = self.file_cache.get_file(info[0].name)
|
|
37
|
-
self.assertEqual(self.file_cache.current_memory_usage, info[2])
|
|
38
|
-
self.assertTrue(info[0].name in self.file_cache.file_futures)
|
|
39
|
-
self.assertEqual(self.file_cache.file_futures[info[0].name][1], info[2])
|
|
40
|
-
self.assertEqual(contents, info[1])
|
|
41
|
-
self.assertEqual(len(self.file_cache.file_access_times), 1)
|
|
42
|
-
self.assertEqual(info[0].name, self.file_cache.file_access_times[0][1])
|
|
43
|
-
|
|
44
|
-
def test_get_file_with_eviction(self):
|
|
45
|
-
for i in range(2):
|
|
46
|
-
for info in self.file_contents.values():
|
|
47
|
-
expected_memory_usage = self.file_cache.current_memory_usage + info[2]
|
|
48
|
-
if expected_memory_usage > self.file_cache.max_memory:
|
|
49
|
-
oldest_size = self.file_cache.file_futures[self.file_cache.file_access_times[0][1]][1]
|
|
50
|
-
expected_memory_usage -= oldest_size
|
|
51
|
-
contents = self.file_cache.get_file(info[0].name)
|
|
52
|
-
self.assertEqual(self.file_cache.current_memory_usage, expected_memory_usage)
|
|
53
|
-
self.assertTrue(info[0].name in self.file_cache.file_futures)
|
|
54
|
-
self.assertEqual(self.file_cache.file_futures[info[0].name][1], info[2])
|
|
55
|
-
self.assertEqual(contents, info[1])
|
|
56
|
-
self.assertEqual(info[0].name, self.file_cache.file_access_times[-1][1])
|
|
57
|
-
|
|
58
|
-
def test_get_file_multithreaded(self):
|
|
59
|
-
def get_file_thread(file, data, size):
|
|
60
|
-
self.assertEqual(self.file_cache.get_file(file.name), data)
|
|
61
|
-
|
|
62
|
-
with ThreadPool() as pool:
|
|
63
|
-
pool.starmap(get_file_thread, random.choices(list(self.file_contents.values()), k=100))
|
|
64
|
-
|
|
65
|
-
def test_unload_file(self):
|
|
66
|
-
for info in self.file_contents.values():
|
|
67
|
-
self.file_cache.get_file(info[0].name)
|
|
68
|
-
self.assertEqual(self.file_cache.current_memory_usage, info[2])
|
|
69
|
-
self.file_cache.unload_file(info[0].name)
|
|
70
|
-
self.assertFalse(info[0].name in self.file_cache.file_futures)
|
|
71
|
-
self.assertEqual(self.file_cache.current_memory_usage, 0)
|
|
72
|
-
self.assertEqual(len(self.file_cache.file_access_times), 0)
|
|
73
|
-
|
|
74
|
-
def test_unload_file_multithreaded(self):
|
|
75
|
-
def unload_file_thread(file, data, size):
|
|
76
|
-
self.file_cache.get_file(file.name)
|
|
77
|
-
self.assertTrue(file.name in self.file_cache.file_futures)
|
|
78
|
-
self.file_cache.unload_file(file.name)
|
|
79
|
-
self.assertFalse(file.name in self.file_cache.file_futures)
|
|
80
|
-
|
|
81
|
-
with ThreadPool() as pool:
|
|
82
|
-
for _ in range(10):
|
|
83
|
-
pool.starmap(unload_file_thread, list(self.file_contents.values()))
|
|
84
|
-
|
|
85
|
-
def test_update_file(self):
|
|
86
|
-
info = self.file_contents[0]
|
|
87
|
-
content = self.file_cache.get_file(info[0].name)
|
|
88
|
-
self.assertEqual(content, info[1])
|
|
89
|
-
|
|
90
|
-
# Update the file in the cache
|
|
91
|
-
new_contents = gen_data()
|
|
92
|
-
updated = self.file_cache.update_file(info[0].name, new_contents)
|
|
93
|
-
self.assertTrue(updated)
|
|
94
|
-
self.assertTrue(info[0].name in self.file_cache.file_futures)
|
|
95
|
-
self.assertEqual(self.file_cache.current_memory_usage, len(new_contents))
|
|
96
|
-
self.assertEqual(len(self.file_cache.file_access_times), 1)
|
|
97
|
-
self.assertEqual(info[0].name, self.file_cache.file_access_times[0][1])
|
|
98
|
-
|
|
99
|
-
# Check that the updated file is returned
|
|
100
|
-
content = self.file_cache.get_file(info[0].name)
|
|
101
|
-
self.assertEqual(content, new_contents)
|
|
102
|
-
|
|
103
|
-
self.file_cache.unload_file(info[0].name)
|
|
104
|
-
self.assertFalse(info[0].name in self.file_cache.file_futures)
|
|
105
|
-
self.assertEqual(self.file_cache.current_memory_usage, 0)
|
|
106
|
-
self.assertEqual(len(self.file_cache.file_access_times), 0)
|
|
107
|
-
|
|
108
|
-
def test_update_file_multithreaded(self):
|
|
109
|
-
def update_file_thread(file, data, size):
|
|
110
|
-
info = (file, data, size)
|
|
111
|
-
updated = self.file_cache.update_file(info[0].name, info[1])
|
|
112
|
-
self.assertTrue(updated)
|
|
113
|
-
content = self.file_cache.get_file(info[0].name)
|
|
114
|
-
self.assertEqual(content, info[1])
|
|
115
|
-
|
|
116
|
-
# Update the file in the cache
|
|
117
|
-
new_contents = gen_data()
|
|
118
|
-
updated = self.file_cache.update_file(info[0].name, new_contents)
|
|
119
|
-
self.assertTrue(updated)
|
|
120
|
-
|
|
121
|
-
# Check that the updated file is returned
|
|
122
|
-
content = self.file_cache.get_file(info[0].name)
|
|
123
|
-
self.assertEqual(content, new_contents)
|
|
124
|
-
|
|
125
|
-
self.file_cache.unload_file(info[0].name)
|
|
126
|
-
self.assertFalse(info[0].name in self.file_cache.file_futures)
|
|
127
|
-
|
|
128
|
-
with ThreadPool() as pool:
|
|
129
|
-
for _ in range(10):
|
|
130
|
-
pool.starmap(update_file_thread, list(self.file_contents.values()))
|
|
131
|
-
|
|
132
|
-
def test_update_file_multithreaded_expected(self):
|
|
133
|
-
info = self.file_contents[0]
|
|
134
|
-
name = info[0].name
|
|
135
|
-
self.failed = False
|
|
136
|
-
self.run = True
|
|
137
|
-
|
|
138
|
-
# Create a list of expected values for each thread
|
|
139
|
-
expected_values = [gen_data() for _ in range(10)]
|
|
140
|
-
all_read_expected_values = [info[1], *expected_values]
|
|
141
|
-
|
|
142
|
-
def update_file_thread(file_name, contents):
|
|
143
|
-
while self.run:
|
|
144
|
-
updated = self.file_cache.update_file(file_name, contents)
|
|
145
|
-
while not updated:
|
|
146
|
-
updated = self.file_cache.update_file(file_name, contents)
|
|
147
|
-
|
|
148
|
-
def get_file_thread():
|
|
149
|
-
while self.run:
|
|
150
|
-
updated_file_1_content = self.file_cache.get_file(name)
|
|
151
|
-
if updated_file_1_content not in all_read_expected_values:
|
|
152
|
-
self.failed = True
|
|
153
|
-
self.assertIn(updated_file_1_content, all_read_expected_values)
|
|
154
|
-
|
|
155
|
-
# Update the test file in multiple threads
|
|
156
|
-
threads = []
|
|
157
|
-
for i in range(10):
|
|
158
|
-
thread = threading.Thread(target=update_file_thread, args=(name, expected_values[i]))
|
|
159
|
-
thread.start()
|
|
160
|
-
threads.append(thread)
|
|
161
|
-
|
|
162
|
-
for i in range(100):
|
|
163
|
-
thread = threading.Thread(target=get_file_thread)
|
|
164
|
-
thread.start()
|
|
165
|
-
threads.append(thread)
|
|
166
|
-
|
|
167
|
-
time.sleep(3)
|
|
168
|
-
self.run = False
|
|
169
|
-
|
|
170
|
-
# Wait for all threads to complete
|
|
171
|
-
for thread in threads:
|
|
172
|
-
thread.join()
|
|
173
|
-
|
|
174
|
-
self.assertFalse(self.failed)
|
|
175
|
-
|
|
176
|
-
# Check that the final contents of the file match one of the expected values
|
|
177
|
-
updated_file_1_content = self.file_cache.get_file(name)
|
|
178
|
-
self.assertIn(updated_file_1_content, expected_values)
|
|
179
|
-
|
|
180
|
-
def tearDown(self):
|
|
181
|
-
for v in self.file_contents.values():
|
|
182
|
-
os.unlink(v[0].name)
|
|
183
|
-
|
|
184
|
-
if __name__ == '__main__':
|
|
185
|
-
unittest.main()
|