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.
Files changed (61) hide show
  1. klongpy/__init__.py +19 -1
  2. klongpy/adverbs.py +5 -5
  3. klongpy/autograd.py +308 -0
  4. klongpy/backend.py +167 -99
  5. klongpy/backends/__init__.py +94 -0
  6. klongpy/backends/base.py +320 -0
  7. klongpy/backends/numpy_backend.py +122 -0
  8. klongpy/backends/torch_backend.py +995 -0
  9. klongpy-0.6.8.data/scripts/kgpy → klongpy/cli.py +65 -88
  10. klongpy/core.py +228 -106
  11. klongpy/db/sys_fn_db.py +4 -3
  12. klongpy/dyads.py +173 -32
  13. klongpy/interpreter.py +31 -3
  14. klongpy/lib/help.kg +2 -2
  15. klongpy/monads.py +49 -12
  16. klongpy/repl.py +91 -0
  17. klongpy/sys_fn.py +129 -18
  18. klongpy/sys_fn_autograd.py +290 -0
  19. klongpy/sys_fn_ipc.py +18 -7
  20. klongpy/sys_fn_timer.py +13 -3
  21. klongpy/web/sys_fn_web.py +28 -6
  22. klongpy-0.7.0.dist-info/METADATA +493 -0
  23. klongpy-0.7.0.dist-info/RECORD +48 -0
  24. {klongpy-0.6.8.dist-info → klongpy-0.7.0.dist-info}/WHEEL +1 -1
  25. klongpy-0.7.0.dist-info/entry_points.txt +2 -0
  26. {klongpy-0.6.8.dist-info → klongpy-0.7.0.dist-info}/top_level.txt +0 -1
  27. klongpy-0.6.8.dist-info/METADATA +0 -412
  28. klongpy-0.6.8.dist-info/RECORD +0 -72
  29. tests/__init__.py +0 -6
  30. tests/gen_join_over.py +0 -119
  31. tests/gen_py_suite.py +0 -77
  32. tests/gen_test_fn.py +0 -259
  33. tests/perf_async.py +0 -25
  34. tests/perf_avg.py +0 -18
  35. tests/perf_duckdb.py +0 -32
  36. tests/perf_gen.py +0 -38
  37. tests/perf_ipc_overhead.py +0 -34
  38. tests/perf_join.py +0 -53
  39. tests/perf_load.py +0 -17
  40. tests/perf_prog.py +0 -18
  41. tests/perf_serdes.py +0 -52
  42. tests/perf_sys_fn_db.py +0 -263
  43. tests/perf_vector.py +0 -40
  44. tests/test_accel.py +0 -227
  45. tests/test_df_cache.py +0 -85
  46. tests/test_examples.py +0 -64
  47. tests/test_extra_suite.py +0 -382
  48. tests/test_file_cache.py +0 -185
  49. tests/test_interop.py +0 -181
  50. tests/test_kgtests.py +0 -65
  51. tests/test_known_bugs.py +0 -206
  52. tests/test_prog.py +0 -107
  53. tests/test_suite.py +0 -1479
  54. tests/test_suite_file.py +0 -153
  55. tests/test_sys_fn.py +0 -420
  56. tests/test_sys_fn_db.py +0 -88
  57. tests/test_sys_fn_ipc.py +0 -587
  58. tests/test_sys_fn_timer.py +0 -133
  59. tests/test_util.py +0 -233
  60. tests/utils.py +0 -126
  61. {klongpy-0.6.8.dist-info → klongpy-0.7.0.dist-info/licenses}/LICENSE +0 -0
@@ -1,4 +1,9 @@
1
- #!python
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.utils import CallbackEvent
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
- sys.exit(0)
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; crtl-d or ]q to quit")
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
- return klong(s)
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
- def append_pkg_resource_path_KLONGPATH():
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
- print(KlongInterpreter()(args.expr))
330
- exit()
331
-
332
- klong = KlongInterpreter()
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
- append_pkg_resource_path_KLONGPATH()
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(f"Failed to start server")
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
- gather_io_tasks(io_loop).wait()
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
- colorama.init(autoreset=True)
395
- show_repl_header(args.server)
396
- console_loop.create_task(ConsoleInputHandler.input_producer(console_loop, klong_loop, klong, args.verbose))
397
- console_loop.run_forever()
398
- console_loop.close()
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
- cleanup_async_loop(io_loop, io_loop_thread, stop_event=io_stop_event, debug=args.debug, name="io_loop")
403
- cleanup_async_loop(klong_loop, klong_loop_thread, stop_event=klong_stop_event, debug=args.debug, name="klong_loop")
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()