klongpy 0.6.8__py3-none-any.whl → 0.6.9__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/core.py +5 -3
- klongpy/dyads.py +14 -4
- klongpy/lib/help.kg +2 -2
- klongpy/monads.py +11 -10
- klongpy/repl.py +73 -0
- klongpy/sys_fn.py +1 -1
- klongpy/sys_fn_ipc.py +0 -1
- klongpy/web/sys_fn_web.py +14 -2
- {klongpy-0.6.8.dist-info → klongpy-0.6.9.dist-info}/METADATA +60 -24
- {klongpy-0.6.8.dist-info → klongpy-0.6.9.dist-info}/RECORD +20 -15
- {klongpy-0.6.8.dist-info → klongpy-0.6.9.dist-info}/WHEEL +1 -1
- tests/test_eval_monad_list.py +34 -0
- tests/test_interop.py +0 -1
- tests/test_kg_asarray.py +94 -0
- tests/test_reshape_strings.py +33 -0
- tests/test_suite.py +1 -0
- tests/test_sys_fn_web.py +50 -0
- {klongpy-0.6.8.data → klongpy-0.6.9.data}/scripts/kgpy +0 -0
- {klongpy-0.6.8.dist-info → klongpy-0.6.9.dist-info/licenses}/LICENSE +0 -0
- {klongpy-0.6.8.dist-info → klongpy-0.6.9.dist-info}/top_level.txt +0 -0
klongpy/core.py
CHANGED
|
@@ -259,17 +259,19 @@ def kg_asarray(a):
|
|
|
259
259
|
arr : ndarray
|
|
260
260
|
The converted input data as a NumPy array, where all elements and sub-arrays are also NumPy arrays.
|
|
261
261
|
"""
|
|
262
|
+
if isinstance(a, str):
|
|
263
|
+
return str_to_chr_arr(a)
|
|
262
264
|
try:
|
|
263
265
|
arr = np.asarray(a)
|
|
264
266
|
if arr.dtype.kind not in ['O','i','f']:
|
|
265
267
|
raise ValueError
|
|
266
268
|
except (np.VisibleDeprecationWarning, ValueError):
|
|
267
269
|
try:
|
|
268
|
-
arr = np.asarray(a,dtype=object)
|
|
270
|
+
arr = np.asarray(a, dtype=object)
|
|
269
271
|
except ValueError:
|
|
270
272
|
arr = [x.tolist() if np.isarray(x) else x for x in a]
|
|
271
|
-
arr = np.asarray(arr,dtype=object)
|
|
272
|
-
arr = np.asarray([kg_asarray(x) if isinstance(x,list) else x for x in arr],dtype=object)
|
|
273
|
+
arr = np.asarray(arr, dtype=object)
|
|
274
|
+
arr = np.asarray([kg_asarray(x) if isinstance(x, list) else x for x in arr], dtype=object)
|
|
273
275
|
return arr
|
|
274
276
|
|
|
275
277
|
|
klongpy/dyads.py
CHANGED
|
@@ -181,7 +181,11 @@ def eval_dyad_at_index(klong, a, b):
|
|
|
181
181
|
j = False
|
|
182
182
|
else:
|
|
183
183
|
r = a
|
|
184
|
-
|
|
184
|
+
if j:
|
|
185
|
+
if np.isarray(r) and r.ndim > 1:
|
|
186
|
+
return np.asarray(["".join(x) for x in r], dtype=object)
|
|
187
|
+
return "".join(r)
|
|
188
|
+
return r
|
|
185
189
|
|
|
186
190
|
|
|
187
191
|
def eval_dyad_define(klong, n, v):
|
|
@@ -401,9 +405,11 @@ def _e_dyad_format2(a, b):
|
|
|
401
405
|
"""
|
|
402
406
|
Unravel the broadcasting of a and b and apply __e_dyad_format2
|
|
403
407
|
"""
|
|
408
|
+
if is_list(a) and is_list(b):
|
|
409
|
+
return kg_asarray([vec_fn2(x, y, _e_dyad_format2) for x, y in zip(to_list(a), to_list(b))])
|
|
404
410
|
if np.isarray(a) and np.isarray(b):
|
|
405
|
-
return np.asarray([vec_fn2(x,y,_e_dyad_format2) for x,y in zip(a,b)])
|
|
406
|
-
return __e_dyad_format2(a,b)
|
|
411
|
+
return np.asarray([vec_fn2(x, y, _e_dyad_format2) for x, y in zip(a, b)])
|
|
412
|
+
return __e_dyad_format2(a, b)
|
|
407
413
|
|
|
408
414
|
def eval_dyad_format2(a, b):
|
|
409
415
|
"""
|
|
@@ -832,7 +838,11 @@ def eval_dyad_reshape(a, b):
|
|
|
832
838
|
r = np.concatenate((np.tile(b,ns), b[:a - b.shape[0]*ns[0]]))
|
|
833
839
|
else:
|
|
834
840
|
r = np.full((a,), b)
|
|
835
|
-
|
|
841
|
+
if j:
|
|
842
|
+
if np.isarray(r) and r.ndim > 1:
|
|
843
|
+
return np.asarray(["".join(x) for x in r], dtype=object)
|
|
844
|
+
return "".join(r)
|
|
845
|
+
return r
|
|
836
846
|
|
|
837
847
|
|
|
838
848
|
def eval_dyad_rotate(a, b):
|
klongpy/lib/help.kg
CHANGED
|
@@ -30,8 +30,8 @@ op.db::[
|
|
|
30
30
|
[" a:$b" "Form"
|
|
31
31
|
"b=string; convert 'b' to an object of the same form (type) as 'a'"]
|
|
32
32
|
[" $a" "Format" "convert 'a' to a string representing the value of 'a'"]
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
[" a$b" "Format2"
|
|
34
|
+
"a=real|list; when both operands are lists, apply pairwise. Format 'b', pad with 'a' blanks or to align to x.y digits"]
|
|
35
35
|
[" >a" "Grade-Down"
|
|
36
36
|
"a=vector; vector of indices of elements of 'a' in ascending order"]
|
|
37
37
|
[" <a" "Grade-Up"
|
klongpy/monads.py
CHANGED
|
@@ -74,7 +74,8 @@ def eval_monad_expand_where(a):
|
|
|
74
74
|
&[0 1 0 1 0] --> [1 3]
|
|
75
75
|
|
|
76
76
|
"""
|
|
77
|
-
|
|
77
|
+
arr = a if is_list(a) else [a]
|
|
78
|
+
return np.repeat(np.arange(len(arr)), arr)
|
|
78
79
|
|
|
79
80
|
|
|
80
81
|
def eval_monad_first(a):
|
|
@@ -163,7 +164,7 @@ def eval_monad_grade_up(a):
|
|
|
163
164
|
>[[1] [2] [3]] --> [2 1 0]
|
|
164
165
|
|
|
165
166
|
"""
|
|
166
|
-
return kg_argsort(
|
|
167
|
+
return kg_argsort(kg_asarray(a))
|
|
167
168
|
|
|
168
169
|
|
|
169
170
|
def eval_monad_grade_down(a):
|
|
@@ -174,7 +175,7 @@ def eval_monad_grade_down(a):
|
|
|
174
175
|
See [Grade-Up].
|
|
175
176
|
|
|
176
177
|
"""
|
|
177
|
-
return kg_argsort(
|
|
178
|
+
return kg_argsort(kg_asarray(a), descending=True)
|
|
178
179
|
|
|
179
180
|
|
|
180
181
|
def eval_monad_groupby(a):
|
|
@@ -194,12 +195,12 @@ def eval_monad_groupby(a):
|
|
|
194
195
|
="hello foo" --> [[0] [1] [2 3] [4 7 8] [5] [6]]
|
|
195
196
|
|
|
196
197
|
"""
|
|
197
|
-
|
|
198
|
-
if
|
|
199
|
-
return
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
return
|
|
198
|
+
arr = kg_asarray(a)
|
|
199
|
+
if arr.size == 0:
|
|
200
|
+
return arr
|
|
201
|
+
vals, inverse = np.unique(arr, return_inverse=True)
|
|
202
|
+
groups = [np.where(inverse == i)[0] for i in range(len(vals))]
|
|
203
|
+
return kg_asarray(groups)
|
|
203
204
|
|
|
204
205
|
|
|
205
206
|
def eval_monad_list(a):
|
|
@@ -217,7 +218,7 @@ def eval_monad_list(a):
|
|
|
217
218
|
if isinstance(a, KGChar):
|
|
218
219
|
return str(a)
|
|
219
220
|
if isinstance(a, KGSym):
|
|
220
|
-
np.asarray([a],dtype=object) # np
|
|
221
|
+
return np.asarray([a],dtype=object) # np interprets ':foo" as ':fo"
|
|
221
222
|
return np.asarray([a])
|
|
222
223
|
|
|
223
224
|
|
klongpy/repl.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import threading
|
|
3
|
+
import time
|
|
4
|
+
import os
|
|
5
|
+
import importlib.resources
|
|
6
|
+
|
|
7
|
+
from . import KlongInterpreter
|
|
8
|
+
from .utils import CallbackEvent
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def start_loop(loop: asyncio.AbstractEventLoop, stop_event: asyncio.Event) -> None:
|
|
12
|
+
asyncio.set_event_loop(loop)
|
|
13
|
+
loop.run_until_complete(stop_event.wait())
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def setup_async_loop(debug: bool = False, slow_callback_duration: float = 86400.0):
|
|
17
|
+
loop = asyncio.new_event_loop()
|
|
18
|
+
loop.slow_callback_duration = slow_callback_duration
|
|
19
|
+
if debug:
|
|
20
|
+
loop.set_debug(True)
|
|
21
|
+
stop_event = asyncio.Event()
|
|
22
|
+
thread = threading.Thread(target=start_loop, args=(loop, stop_event), daemon=True)
|
|
23
|
+
thread.start()
|
|
24
|
+
return loop, thread, stop_event
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def cleanup_async_loop(loop: asyncio.AbstractEventLoop, loop_thread: threading.Thread, stop_event: asyncio.Event, debug: bool = False, name: str | None = None) -> None:
|
|
28
|
+
if loop.is_closed():
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
loop.call_soon_threadsafe(stop_event.set)
|
|
32
|
+
loop_thread.join()
|
|
33
|
+
|
|
34
|
+
pending_tasks = asyncio.all_tasks(loop=loop)
|
|
35
|
+
if len(pending_tasks) > 0:
|
|
36
|
+
if name:
|
|
37
|
+
print(f"WARNING: pending tasks in {name} loop")
|
|
38
|
+
for task in pending_tasks:
|
|
39
|
+
loop.call_soon_threadsafe(task.cancel)
|
|
40
|
+
while len(asyncio.all_tasks(loop=loop)) > 0:
|
|
41
|
+
time.sleep(0)
|
|
42
|
+
|
|
43
|
+
loop.stop()
|
|
44
|
+
|
|
45
|
+
if not loop.is_closed():
|
|
46
|
+
loop.close()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def append_pkg_resource_path_KLONGPATH() -> None:
|
|
50
|
+
with importlib.resources.as_file(importlib.resources.files('klongpy')) as pkg_path:
|
|
51
|
+
pkg_lib_path = os.path.join(pkg_path, 'lib')
|
|
52
|
+
klongpath = os.environ.get('KLONGPATH', '.:lib')
|
|
53
|
+
klongpath = f"{klongpath}:{pkg_lib_path}" if klongpath else str(pkg_lib_path)
|
|
54
|
+
os.environ['KLONGPATH'] = klongpath
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def create_repl(debug: bool = False):
|
|
58
|
+
io_loop, io_thread, io_stop = setup_async_loop(debug=debug)
|
|
59
|
+
klong_loop, klong_thread, klong_stop = setup_async_loop(debug=debug)
|
|
60
|
+
|
|
61
|
+
append_pkg_resource_path_KLONGPATH()
|
|
62
|
+
|
|
63
|
+
klong = KlongInterpreter()
|
|
64
|
+
shutdown_event = CallbackEvent()
|
|
65
|
+
klong['.system'] = {'ioloop': io_loop, 'klongloop': klong_loop, 'closeEvent': shutdown_event}
|
|
66
|
+
|
|
67
|
+
return klong, (io_loop, io_thread, io_stop, klong_loop, klong_thread, klong_stop)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def cleanup_repl(loops, debug: bool = False) -> None:
|
|
71
|
+
io_loop, io_thread, io_stop, klong_loop, klong_thread, klong_stop = loops
|
|
72
|
+
cleanup_async_loop(io_loop, io_thread, io_stop, debug=debug, name='io_loop')
|
|
73
|
+
cleanup_async_loop(klong_loop, klong_thread, klong_stop, debug=debug, name='klong_loop')
|
klongpy/sys_fn.py
CHANGED
|
@@ -405,7 +405,7 @@ def _import_module(klong, x, from_set=None):
|
|
|
405
405
|
module = import_module_from_sys(x)
|
|
406
406
|
|
|
407
407
|
export_items = module.__dict__.get("klongpy_exports") or module.__dict__
|
|
408
|
-
ffn = lambda p: p[0] in from_set if from_set is not None else lambda p: not p[0].startswith("__")
|
|
408
|
+
ffn = (lambda p: p[0] in from_set) if from_set is not None else (lambda p: not p[0].startswith("__"))
|
|
409
409
|
|
|
410
410
|
ctx = klong._context.pop()
|
|
411
411
|
try:
|
klongpy/sys_fn_ipc.py
CHANGED
|
@@ -919,7 +919,6 @@ def eval_sys_fn_create_ipc_server(klong, x):
|
|
|
919
919
|
if "x" is 0, then the server is closed and existing client connections are dropped.
|
|
920
920
|
|
|
921
921
|
"""
|
|
922
|
-
global _ipc_tcp_server
|
|
923
922
|
x = str(x)
|
|
924
923
|
parts = x.split(":")
|
|
925
924
|
bind = parts[0] if len(parts) > 1 else None
|
klongpy/web/sys_fn_web.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import sys
|
|
3
|
+
import asyncio
|
|
4
|
+
import concurrent.futures
|
|
3
5
|
|
|
4
6
|
from aiohttp import web
|
|
5
7
|
|
|
@@ -113,7 +115,17 @@ def eval_sys_fn_create_web_server(klong, x, y, z):
|
|
|
113
115
|
site = web.TCPSite(runner, bind, port)
|
|
114
116
|
await site.start()
|
|
115
117
|
|
|
116
|
-
|
|
118
|
+
# create the server task in the ioloop thread and capture the task handle
|
|
119
|
+
server_loop = klong['.system']['ioloop']
|
|
120
|
+
task_future = concurrent.futures.Future()
|
|
121
|
+
|
|
122
|
+
def _start():
|
|
123
|
+
task = asyncio.create_task(start_server())
|
|
124
|
+
task_future.set_result(task)
|
|
125
|
+
|
|
126
|
+
server_loop.call_soon_threadsafe(_start)
|
|
127
|
+
server_task = task_future.result()
|
|
128
|
+
|
|
117
129
|
return WebServerHandle(bind, port, runner, server_task)
|
|
118
130
|
|
|
119
131
|
|
|
@@ -129,7 +141,7 @@ def eval_sys_fn_shutdown_web_server(klong, x):
|
|
|
129
141
|
x = x.a.fn
|
|
130
142
|
if isinstance(x, WebServerHandle) and x.runner is not None:
|
|
131
143
|
print("shutting down web server")
|
|
132
|
-
klong['.system']['ioloop'].
|
|
144
|
+
asyncio.run_coroutine_threadsafe(x.shutdown(), klong['.system']['ioloop']).result()
|
|
133
145
|
return 1
|
|
134
146
|
return 0
|
|
135
147
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: klongpy
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.9
|
|
4
4
|
Summary: High-Performance Klong array language with rich Python integration.
|
|
5
5
|
Author: Brian Guarraci
|
|
6
6
|
License: MIT
|
|
@@ -10,37 +10,47 @@ Requires-Python: <3.13,>=3.9
|
|
|
10
10
|
Description-Content-Type: text/markdown
|
|
11
11
|
License-File: LICENSE
|
|
12
12
|
Requires-Dist: numpy~=1.26.4
|
|
13
|
-
Provides-Extra: cuda102
|
|
14
|
-
Requires-Dist: cupy-cuda102; extra == "cuda102"
|
|
15
|
-
Provides-Extra: cuda110
|
|
16
|
-
Requires-Dist: cupy-cuda110; extra == "cuda110"
|
|
17
|
-
Provides-Extra: cuda111
|
|
18
|
-
Requires-Dist: cupy-cuda111; extra == "cuda111"
|
|
19
|
-
Provides-Extra: cuda11x
|
|
20
|
-
Requires-Dist: cupy-cuda11x; extra == "cuda11x"
|
|
21
|
-
Provides-Extra: cuda12x
|
|
22
|
-
Requires-Dist: cupy-cuda12x; extra == "cuda12x"
|
|
23
13
|
Provides-Extra: cupy
|
|
24
14
|
Requires-Dist: cupy; extra == "cupy"
|
|
15
|
+
Provides-Extra: cuda12x
|
|
16
|
+
Requires-Dist: cupy-cuda12x; extra == "cuda12x"
|
|
17
|
+
Provides-Extra: cuda11x
|
|
18
|
+
Requires-Dist: cupy-cuda11x; extra == "cuda11x"
|
|
19
|
+
Provides-Extra: cuda111
|
|
20
|
+
Requires-Dist: cupy-cuda111; extra == "cuda111"
|
|
21
|
+
Provides-Extra: cuda110
|
|
22
|
+
Requires-Dist: cupy-cuda110; extra == "cuda110"
|
|
23
|
+
Provides-Extra: cuda102
|
|
24
|
+
Requires-Dist: cupy-cuda102; extra == "cuda102"
|
|
25
|
+
Provides-Extra: rocm-5-0
|
|
26
|
+
Requires-Dist: cupy-rocm-5-0; extra == "rocm-5-0"
|
|
27
|
+
Provides-Extra: rocm-4-3
|
|
28
|
+
Requires-Dist: cupy-rocm-4-3; extra == "rocm-4-3"
|
|
29
|
+
Provides-Extra: repl
|
|
30
|
+
Requires-Dist: colorama==0.4.6; extra == "repl"
|
|
31
|
+
Provides-Extra: web
|
|
32
|
+
Requires-Dist: aiohttp==3.9.4; extra == "web"
|
|
25
33
|
Provides-Extra: db
|
|
26
34
|
Requires-Dist: pandas==2.2.2; extra == "db"
|
|
27
|
-
Requires-Dist: duckdb==1.
|
|
35
|
+
Requires-Dist: duckdb==1.3.0; extra == "db"
|
|
36
|
+
Provides-Extra: ws
|
|
37
|
+
Requires-Dist: websockets==12.0; extra == "ws"
|
|
28
38
|
Provides-Extra: full
|
|
29
39
|
Requires-Dist: colorama==0.4.6; extra == "full"
|
|
30
40
|
Requires-Dist: aiohttp==3.9.4; extra == "full"
|
|
31
41
|
Requires-Dist: pandas==2.2.2; extra == "full"
|
|
32
|
-
Requires-Dist: duckdb==1.
|
|
42
|
+
Requires-Dist: duckdb==1.3.0; extra == "full"
|
|
33
43
|
Requires-Dist: websockets==12.0; extra == "full"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
Dynamic: author
|
|
45
|
+
Dynamic: classifier
|
|
46
|
+
Dynamic: description
|
|
47
|
+
Dynamic: description-content-type
|
|
48
|
+
Dynamic: license
|
|
49
|
+
Dynamic: license-file
|
|
50
|
+
Dynamic: provides-extra
|
|
51
|
+
Dynamic: requires-dist
|
|
52
|
+
Dynamic: requires-python
|
|
53
|
+
Dynamic: summary
|
|
44
54
|
|
|
45
55
|
|
|
46
56
|

|
|
@@ -332,6 +342,31 @@ $ curl http://localhost:8888
|
|
|
332
342
|
['Hello, Klong World! ' 0 1 2 3 4 5 6 7 8 9]
|
|
333
343
|
```
|
|
334
344
|
|
|
345
|
+
You can also spin up this server directly inside the REPL:
|
|
346
|
+
|
|
347
|
+
```kgpy
|
|
348
|
+
?> .py("klongpy.web")
|
|
349
|
+
?> data::!10
|
|
350
|
+
?> index::{x; "Hello, Klong World! ", data}
|
|
351
|
+
?> get:::{}; get,"/",index
|
|
352
|
+
?> post:::{}
|
|
353
|
+
?> h::.web(8888;get;post)
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
And from another terminal:
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
$ curl http://localhost:8888
|
|
360
|
+
['Hello, Klong World! ' 0 1 2 3 4 5 6 7 8 9]
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
Stop the server with:
|
|
364
|
+
|
|
365
|
+
```kgpy
|
|
366
|
+
?> .webc(h)
|
|
367
|
+
1
|
|
368
|
+
```
|
|
369
|
+
|
|
335
370
|
## Conclusion
|
|
336
371
|
|
|
337
372
|
These examples are designed to illustrate the "batteries included" approach, ease of use and diverse applications of KlongPy, making it a versatile choice for various programming needs.
|
|
@@ -388,6 +423,7 @@ KlongPy is effectively a superset of the Klong language, but has some key differ
|
|
|
388
423
|
* Infinite precision: The main difference in this implementation of Klong is the lack of infinite precision. By using NumPy we are restricted to doubles.
|
|
389
424
|
* Python integration: Most notably, the ".py" command allows direct import of Python modules into the current Klong context.
|
|
390
425
|
* KlongPy aims to be more "batteries included" approach to modules and contains additional features such as IPC, Web service, Websockets, etc.
|
|
426
|
+
* For array operations, KlongPy matches the shape of array arguments differently. Compare the results of an expression like `[1 2]+[[3 4][5 6]]` which in Klong produces `[[4 5] [7 8]]` but in KlongPy produces `[[4 6] [6 8]]`.
|
|
391
427
|
|
|
392
428
|
# Related
|
|
393
429
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
klongpy/__init__.py,sha256=8K0RIIZh2QLdOBA68oym_MeEwO33ffcDOZAU3etJ7kA,107
|
|
2
2
|
klongpy/adverbs.py,sha256=W6HAL4rxWV6djrILnahRqw8o6-Yq9pUWIUznSJG8-f0,12566
|
|
3
3
|
klongpy/backend.py,sha256=qA2DulWLVtlOYs3opwJIod0XZVTLCMvqjuttK2_-CHo,2897
|
|
4
|
-
klongpy/core.py,sha256=
|
|
5
|
-
klongpy/dyads.py,sha256=
|
|
4
|
+
klongpy/core.py,sha256=bie-UnhYufNmB7hSKhKmR_dT4X4K8EdrUTiBzk9A3ck,27460
|
|
5
|
+
klongpy/dyads.py,sha256=KkVfKaFnxU6_1-wJNIuwagN_NVwySt9XVP6Sqg0dack,31636
|
|
6
6
|
klongpy/interpreter.py,sha256=AH4LEv3jhgmupgJrvwqMbW_F2EwpmZFKtOMdKc_SJzM,23981
|
|
7
|
-
klongpy/monads.py,sha256=
|
|
8
|
-
klongpy/
|
|
9
|
-
klongpy/
|
|
7
|
+
klongpy/monads.py,sha256=HTpBQKNVbZ7KBnS1xxOsNAwKWUG8xAOXLQIOQR4022g,14076
|
|
8
|
+
klongpy/repl.py,sha256=zwWrxU_KbNfbXAdAJS_wN56bi12w3Jm7HGH6m6Tv0yY,2542
|
|
9
|
+
klongpy/sys_fn.py,sha256=jVhBcUBmKWAgCnZpueyRebYxaWn7fvyDoI_fNx3nw3Y,23729
|
|
10
|
+
klongpy/sys_fn_ipc.py,sha256=okKzZm-FKCyWlDqpL7bnUDZjLqkQVSQK9h20ERItma0,35660
|
|
10
11
|
klongpy/sys_fn_timer.py,sha256=wY9Xx_zA3LOHnAm9ltFvr9OAOXNcnoWQVNYIniDQlSQ,2945
|
|
11
12
|
klongpy/sys_var.py,sha256=x4Jq5JwnQrwdU54vxh03JuunKBb6nQoAGOoxvQAk1w4,4322
|
|
12
13
|
klongpy/utils.py,sha256=nuevztUECi73_H0rrUX8Og19GUEdgkULp5tb2pirhVU,749
|
|
@@ -19,7 +20,7 @@ klongpy/db/sys_fn_kvs.py,sha256=--FTMQyKdn8vBx0qG4mOBzdd2rtBfm0rW4c0AnB0G94,4114
|
|
|
19
20
|
klongpy/lib/csv.kg,sha256=w6FvenQmkl0EF2kieQxxloNOFgZbt3M9IMSYSdImJcA,1498
|
|
20
21
|
klongpy/lib/edt.kg,sha256=aJsjCxAkbfzwxWg8mF9nRDbCCt2fqtCWv0CPsq4SIHw,707
|
|
21
22
|
klongpy/lib/eigenv.kg,sha256=_9iypo9qozqx5HfQR2h8aOx8kYlHGjuZ6NJ4vrfesd4,2118
|
|
22
|
-
klongpy/lib/help.kg,sha256=
|
|
23
|
+
klongpy/lib/help.kg,sha256=p2OobNtxpXMz5xR0DCJwnBonR8Ot86q62r41F2cy4qQ,4309
|
|
23
24
|
klongpy/lib/huffman.kg,sha256=u4vmvzhZ6_-rLgjUH_6HAFMuvqDxhrH1ZWqyNywStOk,637
|
|
24
25
|
klongpy/lib/math.kg,sha256=pIFXlEV_-NzyYobqk3ofvW4Mte-4EqYmSWkwkA8AyLw,10118
|
|
25
26
|
klongpy/lib/nstat.kg,sha256=1besBcCWp067aOv86jHPVmPQMtEWpC41uU1W_pET4yI,18920
|
|
@@ -29,10 +30,11 @@ klongpy/lib/spline.kg,sha256=8kVvX9gsieR5f2hZDx0M_oKmJl7CP6Nn0hJssdcXkwk,1454
|
|
|
29
30
|
klongpy/lib/time.kg,sha256=tJPknPGXHa_239PBMscg2VSaJ3ZV6SVRbADtTtE1a_4,359
|
|
30
31
|
klongpy/lib/util.kg,sha256=LXwPtmcYZUv3Vs5eFt-1RqTvr7cn-_RKLKaSnLLN5gc,440
|
|
31
32
|
klongpy/web/__init__.py,sha256=lM_40n_qzwYSx_OFi4RqFwsxQe8GGBtJm3_GLLxn9-8,101
|
|
32
|
-
klongpy/web/sys_fn_web.py,sha256=
|
|
33
|
+
klongpy/web/sys_fn_web.py,sha256=usfcEWAQyTK0cppPZPefzr_raYoMzZUeh8WZDuvaAMU,5064
|
|
33
34
|
klongpy/ws/__init__.py,sha256=GKl5804W3XNkDER0mkdFf-4cIVjgeP9M3tfNg_tCv3c,114
|
|
34
35
|
klongpy/ws/sys_fn_ws.py,sha256=Ba6MmmTS6cWHlruGgNznNXXPQX2zaBQmAEwkz9ge7sk,18300
|
|
35
|
-
klongpy-0.6.
|
|
36
|
+
klongpy-0.6.9.data/scripts/kgpy,sha256=nDF66LclUBK6qILB2dgJ9VKAlGlPKMQfoJ4CvH5d_UQ,12119
|
|
37
|
+
klongpy-0.6.9.dist-info/licenses/LICENSE,sha256=Nk1iW-tI7n0z8R2jMqVm9SuFIoa8iukXsFcJoPqQgns,1071
|
|
36
38
|
tests/__init__.py,sha256=xdETQVm8SNlASCru27aks1KZwSs2Oh-0NR5zrccSqb0,221
|
|
37
39
|
tests/gen_join_over.py,sha256=ZiliJS6Lz0rqaZAfAeJFbPOU109PRF0QFE6262a4TPU,3684
|
|
38
40
|
tests/gen_py_suite.py,sha256=ihXihalZkjN9Poy3m-1FVGdZy_YYWS0CEkY68pDgGso,2495
|
|
@@ -50,23 +52,26 @@ tests/perf_sys_fn_db.py,sha256=mjoskDzjRJQL4xZULtOm4_y0r2GT8WhgGR1RdhNLjqw,5015
|
|
|
50
52
|
tests/perf_vector.py,sha256=p76TVCS5szG0BX7rzquvKb7xikxUQOUmQttvTS0EH44,976
|
|
51
53
|
tests/test_accel.py,sha256=apKi0PN9l9ztDLTwtdo6esWCl7_Yo97xljfNY0q9hug,6305
|
|
52
54
|
tests/test_df_cache.py,sha256=vK36B0ENNwTYgv_JvRZimum9EEoPw-qgi4BWQWHRqQQ,3302
|
|
55
|
+
tests/test_eval_monad_list.py,sha256=pP7hDxpWIJSg6MD8tya5ctS9d5Z6I2xHnrFbDutkMQY,846
|
|
53
56
|
tests/test_examples.py,sha256=hfpCQlcLR4pjUeSk9uAhtgnsjLEHLc_sfvRRWq8W1iY,2131
|
|
54
57
|
tests/test_extra_suite.py,sha256=WPIA_UcP5BVvZIlkiDMUx_877ts3rYoVLo0grQh4JW8,12967
|
|
55
58
|
tests/test_file_cache.py,sha256=lkE4bXPR9qp6wRdNHcG0f0Fb_BBB-2oocRttmCbXT7A,7733
|
|
56
|
-
tests/test_interop.py,sha256=
|
|
59
|
+
tests/test_interop.py,sha256=1ja39E4p_aHpc1hdWbldAid2MIWCv2raNamYxMrSfwk,5805
|
|
60
|
+
tests/test_kg_asarray.py,sha256=7k2BjUWz7ojRKou2wpEniLNtV9JLTQPkDLmXKh3gph4,2854
|
|
57
61
|
tests/test_kgtests.py,sha256=7lUgKYt9TQiYxAXWqE4VuaZo7frhbzSd9ofa6_pWBLE,2190
|
|
58
62
|
tests/test_known_bugs.py,sha256=shBMW2rwQV0CLtrPZZ54TDFII7W5fxi7AOpZyvbydM8,6481
|
|
59
63
|
tests/test_prog.py,sha256=8P019M-hiW9jxe9FgQS3Q7wqxoTrkhclMTk6xO4HBWU,3311
|
|
60
|
-
tests/
|
|
64
|
+
tests/test_reshape_strings.py,sha256=sZlzKnBuv9ZvUm3sU_PXLr2SXA8gL92n8F0h4gjV528,1063
|
|
65
|
+
tests/test_suite.py,sha256=iBLRwnzEPZWh86lJ9rXUrUMqRUCh-kDl11TsrfPSrWM,73100
|
|
61
66
|
tests/test_suite_file.py,sha256=zZLXK1xEQgUH0OO9J53jkF4j0rjbgIXsWlsNo5puriA,4027
|
|
62
67
|
tests/test_sys_fn.py,sha256=iGoalDXEw2LEIRGYgYIhc1rc-rU5wCNbRyvcr6nYoPw,15695
|
|
63
68
|
tests/test_sys_fn_db.py,sha256=iX5sSJGzVMaN_GnhNQE_b6mWCIUYrDmE25KdubXNQL8,2471
|
|
64
69
|
tests/test_sys_fn_ipc.py,sha256=tV7uCGxXQCHZQ2CkffD4j5h01TYBe1ozC_wImiANyHA,21605
|
|
65
70
|
tests/test_sys_fn_timer.py,sha256=VUfi1AK9SCzA9g5IgbfpdEMW2AP4-9dgVOpJXhMMQhA,4447
|
|
71
|
+
tests/test_sys_fn_web.py,sha256=TQX2R_4DCR2YOnhITFpTibL6_4UNbAphiix0fOuFv0Q,1552
|
|
66
72
|
tests/test_util.py,sha256=k4UCR0avjWNxo_jO710x32AAMOAePOx79EOt58wL584,7942
|
|
67
73
|
tests/utils.py,sha256=QrLAR4-WXVSDrC60qhl78_NE-3idp0mgLJmSZ5seyWw,3721
|
|
68
|
-
klongpy-0.6.
|
|
69
|
-
klongpy-0.6.
|
|
70
|
-
klongpy-0.6.
|
|
71
|
-
klongpy-0.6.
|
|
72
|
-
klongpy-0.6.8.dist-info/RECORD,,
|
|
74
|
+
klongpy-0.6.9.dist-info/METADATA,sha256=49HaLNk5_XaBlB3Uq6U_hFN8w04_rYHBd7-ipbU-Cbc,17249
|
|
75
|
+
klongpy-0.6.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
76
|
+
klongpy-0.6.9.dist-info/top_level.txt,sha256=1dsI3MhtibeAZuB7WPW58dpNgyGvXLX5EEHqm46NQYo,14
|
|
77
|
+
klongpy-0.6.9.dist-info/RECORD,,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from klongpy import KlongInterpreter
|
|
5
|
+
from klongpy.core import KGSym
|
|
6
|
+
from tests.utils import kg_equal
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestEvalMonadList(unittest.TestCase):
|
|
10
|
+
|
|
11
|
+
def setUp(self):
|
|
12
|
+
self.klong = KlongInterpreter()
|
|
13
|
+
|
|
14
|
+
def test_int(self):
|
|
15
|
+
r = self.klong(',1')
|
|
16
|
+
self.assertTrue(kg_equal(r, np.asarray([1])))
|
|
17
|
+
|
|
18
|
+
def test_symbol(self):
|
|
19
|
+
r = self.klong(',:foo')
|
|
20
|
+
self.assertTrue(r.dtype == object)
|
|
21
|
+
self.assertEqual(len(r), 1)
|
|
22
|
+
self.assertEqual(r[0], KGSym('foo'))
|
|
23
|
+
|
|
24
|
+
def test_string(self):
|
|
25
|
+
r = self.klong(',"xyz"')
|
|
26
|
+
self.assertTrue(kg_equal(r, np.asarray(['xyz'], dtype=object)))
|
|
27
|
+
|
|
28
|
+
def test_list(self):
|
|
29
|
+
r = self.klong(',[1]')
|
|
30
|
+
self.assertTrue(kg_equal(r, np.asarray([[1]], dtype=object)))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
if __name__ == '__main__':
|
|
34
|
+
unittest.main()
|
tests/test_interop.py
CHANGED
tests/test_kg_asarray.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from klongpy.core import kg_asarray, KGChar, KGSym
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestKGAsArray(unittest.TestCase):
|
|
9
|
+
|
|
10
|
+
def test_kg_asarray_scalar_int(self):
|
|
11
|
+
x = 42
|
|
12
|
+
arr = kg_asarray(x)
|
|
13
|
+
assert np.isarray(arr)
|
|
14
|
+
assert arr.dtype == int
|
|
15
|
+
assert arr.shape == ()
|
|
16
|
+
assert arr.item() == 42
|
|
17
|
+
|
|
18
|
+
def test_kg_asarray_scalar_float(self):
|
|
19
|
+
x = 3.14
|
|
20
|
+
arr = kg_asarray(x)
|
|
21
|
+
assert np.isarray(arr)
|
|
22
|
+
assert arr.dtype == float
|
|
23
|
+
assert arr.item() == 3.14
|
|
24
|
+
|
|
25
|
+
def test_kg_asarray_empty_list(self):
|
|
26
|
+
x = []
|
|
27
|
+
arr = kg_asarray(x)
|
|
28
|
+
assert np.isarray(arr)
|
|
29
|
+
assert arr.dtype == float # default dtype for empty list
|
|
30
|
+
assert arr.size == 0
|
|
31
|
+
|
|
32
|
+
def test_kg_asarray_string(self):
|
|
33
|
+
s = "hello"
|
|
34
|
+
arr = kg_asarray(s)
|
|
35
|
+
assert np.isarray(arr)
|
|
36
|
+
assert arr.dtype == object # assuming KGChar is object dtype
|
|
37
|
+
assert "".join(arr) == "hello"
|
|
38
|
+
|
|
39
|
+
def test_kg_asarray_list_of_ints(self):
|
|
40
|
+
x = [1, 2, 3]
|
|
41
|
+
arr = kg_asarray(x)
|
|
42
|
+
assert np.isarray(arr)
|
|
43
|
+
assert arr.dtype == int
|
|
44
|
+
assert np.array_equal(arr, [1, 2, 3])
|
|
45
|
+
|
|
46
|
+
def test_kg_asarray_nested_list_uniform(self):
|
|
47
|
+
x = [[1, 2], [3, 4]]
|
|
48
|
+
arr = kg_asarray(x)
|
|
49
|
+
assert np.isarray(arr)
|
|
50
|
+
assert arr.shape == (2,2)
|
|
51
|
+
assert arr.dtype == int
|
|
52
|
+
assert np.array_equal(arr, [[1,2],[3,4]])
|
|
53
|
+
|
|
54
|
+
@unittest.skip("what is the expected behavior for this case?")
|
|
55
|
+
def test_kg_asarray_nested_list_heterogeneous(self):
|
|
56
|
+
# should embedded strings be expanded to individual characters?
|
|
57
|
+
x = [[1, 2], "abc", [3.14, None]]
|
|
58
|
+
arr = kg_asarray(x)
|
|
59
|
+
assert np.isarray(arr)
|
|
60
|
+
# Because of heterogeneous data, dtype should be object.
|
|
61
|
+
assert arr.dtype == object
|
|
62
|
+
# Check that sub-elements are arrays
|
|
63
|
+
assert np.isarray(arr[0])
|
|
64
|
+
assert np.isarray(arr[1])
|
|
65
|
+
assert np.isarray(arr[2])
|
|
66
|
+
|
|
67
|
+
def test_kg_asarray_already_array(self):
|
|
68
|
+
x = np.array([1, 2, 3])
|
|
69
|
+
arr = kg_asarray(x)
|
|
70
|
+
# Should return as-is because already suitable dtype
|
|
71
|
+
assert arr is x
|
|
72
|
+
|
|
73
|
+
def test_kg_asarray_jagged_list(self):
|
|
74
|
+
x = [[1, 2, 3], [4, 5], [6]]
|
|
75
|
+
arr = kg_asarray(x)
|
|
76
|
+
assert np.isarray(arr)
|
|
77
|
+
# Jagged => object dtype
|
|
78
|
+
assert arr.dtype == object
|
|
79
|
+
# Each element should be an array
|
|
80
|
+
assert all(np.isarray(e) for e in arr)
|
|
81
|
+
assert np.array_equal(arr[0], [1, 2, 3])
|
|
82
|
+
assert np.array_equal(arr[1], [4, 5])
|
|
83
|
+
assert np.array_equal(arr[2], [6])
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def benchmark_kg_asarray(self):
|
|
87
|
+
import timeit
|
|
88
|
+
x = [[1, 2], [3, 4]]
|
|
89
|
+
print(timeit.timeit(lambda: kg_asarray(x), number=100_000))
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if __name__ == "__main__":
|
|
93
|
+
# run the benchmark
|
|
94
|
+
TestKGAsArray().benchmark_kg_asarray()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from klongpy import KlongInterpreter
|
|
5
|
+
from tests.utils import kg_equal
|
|
6
|
+
|
|
7
|
+
class TestReshapeStrings(unittest.TestCase):
|
|
8
|
+
def setUp(self):
|
|
9
|
+
self.klong = KlongInterpreter()
|
|
10
|
+
|
|
11
|
+
def test_reshape_string_len1(self):
|
|
12
|
+
r = self.klong('[2 2]:^"a"')
|
|
13
|
+
self.assertTrue(kg_equal(r, np.asarray(["aa", "aa"], dtype=object)))
|
|
14
|
+
|
|
15
|
+
def test_reshape_string_len2(self):
|
|
16
|
+
r = self.klong('[2 2]:^"ab"')
|
|
17
|
+
self.assertTrue(kg_equal(r, np.asarray(["ab", "ab"], dtype=object)))
|
|
18
|
+
|
|
19
|
+
def test_reshape_string_len3(self):
|
|
20
|
+
r = self.klong('[2 2]:^"abc"')
|
|
21
|
+
self.assertTrue(kg_equal(r, np.asarray(["ab", "ca"], dtype=object)))
|
|
22
|
+
|
|
23
|
+
def test_reshape_string_len4(self):
|
|
24
|
+
r = self.klong('[2 2]:^"abcd"')
|
|
25
|
+
self.assertTrue(kg_equal(r, np.asarray(["ab", "cd"], dtype=object)))
|
|
26
|
+
|
|
27
|
+
def test_reshape_string_larger_shape(self):
|
|
28
|
+
r = self.klong('[3 3]:^"abcd"')
|
|
29
|
+
self.assertTrue(kg_equal(r, np.asarray(["abc", "dab", "cda"], dtype=object)))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
if __name__ == '__main__':
|
|
33
|
+
unittest.main()
|
tests/test_suite.py
CHANGED
|
@@ -484,6 +484,7 @@ class TestCoreSuite(unittest.TestCase):
|
|
|
484
484
|
self.assert_eval_cmp('5$1.23', '"1.23 "')
|
|
485
485
|
self.assert_eval_cmp('5$-1.23', '"-1.23"')
|
|
486
486
|
self.assert_eval_cmp('6$-1.23', '"-1.23 "')
|
|
487
|
+
self.assert_eval_cmp('[1]$[1]', '["1"]')
|
|
487
488
|
self.assert_eval_cmp('(-10)$0', '" 0"')
|
|
488
489
|
self.assert_eval_cmp('(-10)$123', '" 123"')
|
|
489
490
|
self.assert_eval_cmp('(-10)$-123', '" -123"')
|
tests/test_sys_fn_web.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import socket
|
|
3
|
+
import unittest
|
|
4
|
+
|
|
5
|
+
import aiohttp
|
|
6
|
+
|
|
7
|
+
from klongpy.repl import create_repl, cleanup_repl
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestSysFnWeb(unittest.TestCase):
|
|
11
|
+
def setUp(self):
|
|
12
|
+
self.klong, self.loops = create_repl()
|
|
13
|
+
(self.ioloop, self.ioloop_thread, self.io_stop,
|
|
14
|
+
self.klongloop, self.klongloop_thread, self.klong_stop) = self.loops
|
|
15
|
+
self.handle = None
|
|
16
|
+
|
|
17
|
+
def tearDown(self):
|
|
18
|
+
if self.handle is not None and self.handle.task is not None:
|
|
19
|
+
asyncio.run_coroutine_threadsafe(self.handle.shutdown(), self.ioloop).result()
|
|
20
|
+
cleanup_repl(self.loops)
|
|
21
|
+
|
|
22
|
+
def _free_port(self):
|
|
23
|
+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
24
|
+
s.bind(("", 0))
|
|
25
|
+
port = s.getsockname()[1]
|
|
26
|
+
s.close()
|
|
27
|
+
return port
|
|
28
|
+
|
|
29
|
+
def test_web_server_start_and_stop(self):
|
|
30
|
+
klong = self.klong
|
|
31
|
+
port = self._free_port()
|
|
32
|
+
|
|
33
|
+
klong('.py("klongpy.web")')
|
|
34
|
+
klong('index::{x;"hello"}')
|
|
35
|
+
klong('get:::{}')
|
|
36
|
+
klong('get,"/",index')
|
|
37
|
+
klong('post:::{}')
|
|
38
|
+
handle = klong(f'h::.web({port};get;post)')
|
|
39
|
+
self.handle = handle
|
|
40
|
+
|
|
41
|
+
async def fetch():
|
|
42
|
+
async with aiohttp.ClientSession() as session:
|
|
43
|
+
async with session.get(f"http://localhost:{port}/") as resp:
|
|
44
|
+
return await resp.text()
|
|
45
|
+
|
|
46
|
+
response = asyncio.run_coroutine_threadsafe(fetch(), self.ioloop).result()
|
|
47
|
+
self.assertEqual(response, "hello")
|
|
48
|
+
|
|
49
|
+
asyncio.run_coroutine_threadsafe(handle.shutdown(), self.ioloop).result()
|
|
50
|
+
|
|
File without changes
|
|
File without changes
|
|
File without changes
|