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
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
KlongPy REPL command-line interface.
|
|
4
|
+
|
|
5
|
+
See https://t3x.org/klong/klong-ref.txt.html for additional details.
|
|
6
|
+
"""
|
|
2
7
|
|
|
3
8
|
import argparse
|
|
4
9
|
import asyncio
|
|
@@ -6,22 +11,14 @@ import importlib.metadata
|
|
|
6
11
|
import os
|
|
7
12
|
import sys
|
|
8
13
|
import threading
|
|
9
|
-
import time
|
|
10
14
|
import timeit
|
|
11
15
|
|
|
12
16
|
import colorama
|
|
13
17
|
|
|
14
18
|
from klongpy import KlongInterpreter
|
|
15
19
|
from klongpy.core import kg_write
|
|
16
|
-
from klongpy.
|
|
20
|
+
from klongpy.repl import cleanup_repl, create_repl
|
|
17
21
|
|
|
18
|
-
import importlib.resources
|
|
19
|
-
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
KlongPy REPL: See https://t3x.org/klong/klong-ref.txt.html for additional details.
|
|
23
|
-
|
|
24
|
-
"""
|
|
25
22
|
|
|
26
23
|
def sys_cmd_shell(klong, cmd):
|
|
27
24
|
"""
|
|
@@ -112,7 +109,7 @@ def sys_cmd_exit(klong, cmd):
|
|
|
112
109
|
|
|
113
110
|
"""
|
|
114
111
|
print("bye!")
|
|
115
|
-
|
|
112
|
+
return ExitRequest(0)
|
|
116
113
|
|
|
117
114
|
|
|
118
115
|
def sys_cmd_transcript(klong, cmd):
|
|
@@ -174,10 +171,17 @@ success = lambda input: f"{colorama.Fore.GREEN}{input}"
|
|
|
174
171
|
failure = lambda input: f"{colorama.Fore.RED}{input}"
|
|
175
172
|
|
|
176
173
|
|
|
174
|
+
class ExitRequest:
|
|
175
|
+
def __init__(self, code=0):
|
|
176
|
+
self.code = 0 if code is None else code
|
|
177
|
+
|
|
178
|
+
|
|
177
179
|
async def repl_eval(klong, p, verbose=True):
|
|
178
180
|
try:
|
|
179
181
|
r = klong(p)
|
|
180
|
-
r = r if r is None else success(kg_write(r, display=False))
|
|
182
|
+
r = r if r is None else success(kg_write(r, klong._backend, display=False))
|
|
183
|
+
except SystemExit as exc:
|
|
184
|
+
return ExitRequest(exc.code)
|
|
181
185
|
except Exception as e:
|
|
182
186
|
r = failure(f"Error: {e.args}")
|
|
183
187
|
if verbose:
|
|
@@ -192,7 +196,7 @@ def show_repl_header(ipc_addr=None):
|
|
|
192
196
|
print(f"{colorama.Fore.GREEN}Welcome to KlongPy REPL v{importlib.metadata.distribution('klongpy').version}")
|
|
193
197
|
print(f"{colorama.Fore.GREEN}Author: Brian Guarraci")
|
|
194
198
|
print(f"{colorama.Fore.GREEN}Web: http://klongpy.org")
|
|
195
|
-
print(f"{colorama.Fore.YELLOW}]h for help;
|
|
199
|
+
print(f"{colorama.Fore.YELLOW}]h for help; Ctrl-D or ]q to quit")
|
|
196
200
|
print()
|
|
197
201
|
if ipc_addr:
|
|
198
202
|
print(f"{colorama.Fore.RED}Running IPC server at {ipc_addr}")
|
|
@@ -209,7 +213,7 @@ def run_in_loop(klong_loop, coro):
|
|
|
209
213
|
|
|
210
214
|
class ConsoleInputHandler:
|
|
211
215
|
@staticmethod
|
|
212
|
-
async def input_producer(console_loop, klong_loop, klong, verbose=False):
|
|
216
|
+
async def input_producer(console_loop, klong_loop, klong, verbose=False, exit_state=None):
|
|
213
217
|
sys_cmds = create_sys_cmd_functions()
|
|
214
218
|
try:
|
|
215
219
|
while True:
|
|
@@ -225,6 +229,10 @@ class ConsoleInputHandler:
|
|
|
225
229
|
continue
|
|
226
230
|
else:
|
|
227
231
|
r = run_in_loop(klong_loop, repl_eval(klong, s, verbose=verbose))
|
|
232
|
+
if isinstance(r, ExitRequest):
|
|
233
|
+
if exit_state is not None:
|
|
234
|
+
exit_state["code"] = r.code
|
|
235
|
+
break
|
|
228
236
|
if r is not None:
|
|
229
237
|
print(r)
|
|
230
238
|
except EOFError:
|
|
@@ -241,65 +249,20 @@ class ConsoleInputHandler:
|
|
|
241
249
|
|
|
242
250
|
|
|
243
251
|
async def run_in_klong(klong, s):
|
|
244
|
-
|
|
252
|
+
try:
|
|
253
|
+
return klong(s)
|
|
254
|
+
except SystemExit as exc:
|
|
255
|
+
return ExitRequest(exc.code)
|
|
245
256
|
|
|
246
257
|
|
|
247
258
|
def run_file(klong_loop, klong, fname, verbose=False):
|
|
248
259
|
with open(fname, "r") as f:
|
|
249
260
|
content = f.read()
|
|
250
|
-
run_in_loop(klong_loop, run_in_klong(klong, content))
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
def start_loop(loop, stop_event):
|
|
254
|
-
asyncio.set_event_loop(loop)
|
|
255
|
-
loop.run_until_complete(stop_event.wait())
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
def setup_async_loop(start_loop_func, debug=False, slow_callback_duration=86400) -> asyncio.AbstractEventLoop:
|
|
259
|
-
loop = asyncio.new_event_loop()
|
|
260
|
-
loop.slow_callback_duration = slow_callback_duration
|
|
261
|
-
if debug:
|
|
262
|
-
loop.set_debug(True)
|
|
263
|
-
stop_event = asyncio.Event()
|
|
264
|
-
thread = threading.Thread(target=lambda l=loop,e=stop_event: start_loop_func(l,e), args=(loop,), daemon=True)
|
|
265
|
-
thread.start()
|
|
266
|
-
return loop, thread, stop_event
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
def cleanup_async_loop(loop: asyncio.AbstractEventLoop, loop_thread, stop_event, debug=True, name=None) -> None:
|
|
261
|
+
return run_in_loop(klong_loop, run_in_klong(klong, content))
|
|
270
262
|
|
|
271
|
-
if loop.is_closed():
|
|
272
|
-
return
|
|
273
|
-
|
|
274
|
-
loop.call_soon_threadsafe(stop_event.set)
|
|
275
|
-
loop_thread.join()
|
|
276
|
-
|
|
277
|
-
pending_tasks = asyncio.all_tasks(loop=loop)
|
|
278
|
-
if len(pending_tasks) > 0:
|
|
279
|
-
if name:
|
|
280
|
-
print(f"WARNING: pending tasks in {name} loop")
|
|
281
|
-
print(f"cancelling {len(pending_tasks)} pending tasks...")
|
|
282
|
-
for task in pending_tasks:
|
|
283
|
-
loop.call_soon_threadsafe(task.cancel)
|
|
284
|
-
# wait for all tasks to be cancelled but we can't use run_until_complete because the loop is already running
|
|
285
|
-
while len(asyncio.all_tasks(loop=loop)) > 0:
|
|
286
|
-
time.sleep(0)
|
|
287
|
-
|
|
288
|
-
loop.stop()
|
|
289
|
-
|
|
290
|
-
if not loop.is_closed():
|
|
291
|
-
loop.close()
|
|
292
263
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
with importlib.resources.as_file(importlib.resources.files('klongpy')) as pkg_path:
|
|
296
|
-
pkg_lib_path = os.path.join(pkg_path, "lib")
|
|
297
|
-
klongpath = os.environ.get("KLONGPATH", ".:lib")
|
|
298
|
-
klongpath = f"{klongpath}:{pkg_lib_path}" if klongpath else str(pkg_lib_path)
|
|
299
|
-
os.environ["KLONGPATH"] = klongpath
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if __name__ == "__main__":
|
|
264
|
+
def main():
|
|
265
|
+
"""Main entry point for the KlongPy REPL."""
|
|
303
266
|
if '--' in sys.argv:
|
|
304
267
|
index = sys.argv.index('--')
|
|
305
268
|
main_args = sys.argv[:index]
|
|
@@ -326,29 +289,27 @@ if __name__ == "__main__":
|
|
|
326
289
|
print("args: ", args)
|
|
327
290
|
|
|
328
291
|
if args.expr:
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
io_loop, io_loop_thread, io_stop_event = setup_async_loop(start_loop, debug=args.debug)
|
|
335
|
-
klong_loop, klong_loop_thread, klong_stop_event = setup_async_loop(start_loop, debug=args.debug)
|
|
336
|
-
|
|
337
|
-
shutdown_event = CallbackEvent()
|
|
292
|
+
klong = KlongInterpreter()
|
|
293
|
+
result = klong(args.expr)
|
|
294
|
+
if result is not None:
|
|
295
|
+
print(kg_write(result, klong._backend, display=False))
|
|
296
|
+
return
|
|
338
297
|
|
|
339
|
-
|
|
298
|
+
klong, loops = create_repl(debug=args.debug)
|
|
299
|
+
io_loop, _, _, klong_loop, _, _ = loops
|
|
300
|
+
shutdown_event = klong['.system']['closeEvent']
|
|
340
301
|
|
|
341
302
|
klong['.helpdb'] = []
|
|
342
|
-
klong['.system'] = {'ioloop': io_loop, 'klongloop': klong_loop, 'closeEvent': shutdown_event}
|
|
343
303
|
klong['.os.env'] = dict(os.environ)
|
|
344
304
|
klong['.os.argv'] = extras if extras else []
|
|
345
305
|
|
|
346
306
|
run_repl = False
|
|
307
|
+
exit_code = None
|
|
347
308
|
|
|
348
309
|
if args.server:
|
|
349
310
|
r = klong(f".srv({args.server})")
|
|
350
311
|
if r == 0:
|
|
351
|
-
print(
|
|
312
|
+
print("Failed to start server")
|
|
352
313
|
elif args.test:
|
|
353
314
|
print(f"Test: {args.test}")
|
|
354
315
|
with open(args.test, "r") as f:
|
|
@@ -362,7 +323,9 @@ if __name__ == "__main__":
|
|
|
362
323
|
if args.filename:
|
|
363
324
|
if args.verbose:
|
|
364
325
|
print(f"Running: {args.filename}")
|
|
365
|
-
run_file(klong_loop, klong, args.filename, verbose=args.verbose)
|
|
326
|
+
result = run_file(klong_loop, klong, args.filename, verbose=args.verbose)
|
|
327
|
+
if isinstance(result, ExitRequest):
|
|
328
|
+
exit_code = result.code
|
|
366
329
|
|
|
367
330
|
def gather_io_tasks(io_loop):
|
|
368
331
|
done_event = threading.Event()
|
|
@@ -377,7 +340,8 @@ if __name__ == "__main__":
|
|
|
377
340
|
done_event.set()
|
|
378
341
|
return done_event
|
|
379
342
|
|
|
380
|
-
|
|
343
|
+
if exit_code is None:
|
|
344
|
+
gather_io_tasks(io_loop).wait()
|
|
381
345
|
else:
|
|
382
346
|
run_repl = True
|
|
383
347
|
|
|
@@ -390,14 +354,27 @@ if __name__ == "__main__":
|
|
|
390
354
|
if args.load:
|
|
391
355
|
if args.verbose:
|
|
392
356
|
print(f"Loading: {args.load}")
|
|
393
|
-
run_file(klong_loop, klong, args.load, verbose=args.verbose)
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
357
|
+
result = run_file(klong_loop, klong, args.load, verbose=args.verbose)
|
|
358
|
+
if isinstance(result, ExitRequest):
|
|
359
|
+
exit_code = result.code
|
|
360
|
+
run_repl = False
|
|
361
|
+
if run_repl:
|
|
362
|
+
exit_state = {"code": None}
|
|
363
|
+
colorama.init(autoreset=True)
|
|
364
|
+
show_repl_header(args.server)
|
|
365
|
+
console_loop.create_task(ConsoleInputHandler.input_producer(console_loop, klong_loop, klong, args.verbose, exit_state))
|
|
366
|
+
console_loop.run_forever()
|
|
367
|
+
console_loop.close()
|
|
368
|
+
if exit_state["code"] is not None:
|
|
369
|
+
exit_code = exit_state["code"]
|
|
399
370
|
|
|
400
371
|
shutdown_event.trigger()
|
|
401
372
|
|
|
402
|
-
|
|
403
|
-
|
|
373
|
+
cleanup_repl(loops, debug=args.debug)
|
|
374
|
+
|
|
375
|
+
if exit_code is not None:
|
|
376
|
+
sys.exit(exit_code)
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
if __name__ == "__main__":
|
|
380
|
+
main()
|