amalgam-lang 20.0.2__py3-none-macosx_12_0_arm64.whl → 25.2.5__py3-none-macosx_12_0_arm64.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.
Potentially problematic release.
This version of amalgam-lang might be problematic. Click here for more details.
- amalgam/api.py +297 -85
- amalgam/lib/darwin/arm64/amalgam-mt.dylib +0 -0
- amalgam/lib/darwin/arm64/amalgam-omp.dylib +0 -0
- amalgam/lib/darwin/arm64/amalgam-st.dylib +0 -0
- amalgam/lib/darwin/arm64/docs/version.json +1 -1
- amalgam/lib/version.json +3 -3
- {amalgam_lang-20.0.2.dist-info → amalgam_lang-25.2.5.dist-info}/METADATA +3 -4
- amalgam_lang-25.2.5.dist-info/RECORD +12 -0
- amalgam_lang-20.0.2.dist-info/RECORD +0 -12
- {amalgam_lang-20.0.2.dist-info → amalgam_lang-25.2.5.dist-info}/WHEEL +0 -0
- {amalgam_lang-20.0.2.dist-info → amalgam_lang-25.2.5.dist-info}/licenses/LICENSE.txt +0 -0
- {amalgam_lang-20.0.2.dist-info → amalgam_lang-25.2.5.dist-info}/top_level.txt +0 -0
amalgam/api.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from base64 import b64encode
|
|
3
4
|
from ctypes import (
|
|
4
5
|
_Pointer, Array, byref, c_bool, c_char, c_char_p, c_size_t, c_uint64, c_void_p,
|
|
5
|
-
cast, cdll, POINTER, Structure
|
|
6
|
+
cast, cdll, POINTER, Structure, string_at
|
|
6
7
|
)
|
|
7
8
|
from datetime import datetime
|
|
8
9
|
import gc
|
|
@@ -28,7 +29,9 @@ class _LoadEntityStatus(Structure):
|
|
|
28
29
|
_fields_ = [
|
|
29
30
|
("loaded", c_bool),
|
|
30
31
|
("message", POINTER(c_char)),
|
|
31
|
-
("version", POINTER(c_char))
|
|
32
|
+
("version", POINTER(c_char)),
|
|
33
|
+
("entity_path", POINTER(POINTER(c_char))),
|
|
34
|
+
("entity_path_len", c_size_t)
|
|
32
35
|
]
|
|
33
36
|
|
|
34
37
|
|
|
@@ -53,10 +56,14 @@ class LoadEntityStatus:
|
|
|
53
56
|
self.loaded = True
|
|
54
57
|
self.message = ""
|
|
55
58
|
self.version = ""
|
|
59
|
+
self.entity_path = []
|
|
56
60
|
else:
|
|
57
61
|
self.loaded = bool(c_status.loaded)
|
|
58
62
|
self.message = api.char_p_to_str(c_status.message)
|
|
59
63
|
self.version = api.char_p_to_str(c_status.version)
|
|
64
|
+
self.entity_path = [api.char_p_to_str(c_status.entity_path[i]) for i in range(c_status.entity_path_len)]
|
|
65
|
+
api.amlg.DeleteString(cast(c_status.entity_path, c_char_p))
|
|
66
|
+
|
|
60
67
|
|
|
61
68
|
def __str__(self) -> str:
|
|
62
69
|
"""
|
|
@@ -67,7 +74,11 @@ class LoadEntityStatus:
|
|
|
67
74
|
str
|
|
68
75
|
The human-readable string representation.
|
|
69
76
|
"""
|
|
70
|
-
|
|
77
|
+
ep = ""
|
|
78
|
+
if self.entity_path:
|
|
79
|
+
eps = (f'"{step}"' for step in self.entity_path)
|
|
80
|
+
ep = f",[{','.join(eps)}]"
|
|
81
|
+
return f"{self.loaded},\"{self.message}\",\"{self.version}\"{ep}"
|
|
71
82
|
|
|
72
83
|
|
|
73
84
|
class _ResultWithLog(Structure):
|
|
@@ -237,8 +248,7 @@ class Amalgam:
|
|
|
237
248
|
)
|
|
238
249
|
counter += 1
|
|
239
250
|
|
|
240
|
-
self.trace =
|
|
241
|
-
encoding='utf-8')
|
|
251
|
+
self.trace = self.execution_trace_filepath.open("wb+")
|
|
242
252
|
_logger.debug("Opening Amalgam trace file: "
|
|
243
253
|
f"{self.execution_trace_filepath}")
|
|
244
254
|
else:
|
|
@@ -253,7 +263,7 @@ class Amalgam:
|
|
|
253
263
|
self.set_max_num_threads(max_num_threads)
|
|
254
264
|
self.gc_interval = gc_interval
|
|
255
265
|
self.op_count = 0
|
|
256
|
-
self.load_command_log_entry = None
|
|
266
|
+
self.load_command_log_entry: bytes | None = None
|
|
257
267
|
|
|
258
268
|
@classmethod
|
|
259
269
|
def _get_allowed_postfixes(cls, library_dir: Path) -> list[str]:
|
|
@@ -470,7 +480,7 @@ class Amalgam:
|
|
|
470
480
|
The maximum number of threads that Amalgam is configured to use.
|
|
471
481
|
"""
|
|
472
482
|
self.amlg.GetMaxNumThreads.restype = c_size_t
|
|
473
|
-
self._log_execution("GET_MAX_NUM_THREADS")
|
|
483
|
+
self._log_execution(b"GET_MAX_NUM_THREADS")
|
|
474
484
|
result = self.amlg.GetMaxNumThreads()
|
|
475
485
|
self._log_reply(result)
|
|
476
486
|
|
|
@@ -492,7 +502,7 @@ class Amalgam:
|
|
|
492
502
|
self.amlg.SetMaxNumThreads.argtypes = [c_size_t]
|
|
493
503
|
self.amlg.SetMaxNumThreads.restype = c_void_p
|
|
494
504
|
|
|
495
|
-
self._log_execution(f"SET_MAX_NUM_THREADS {max_num_threads}")
|
|
505
|
+
self._log_execution(f"SET_MAX_NUM_THREADS {max_num_threads}".encode())
|
|
496
506
|
result = self.amlg.SetMaxNumThreads(max_num_threads)
|
|
497
507
|
self._log_reply(result)
|
|
498
508
|
|
|
@@ -511,7 +521,7 @@ class Amalgam:
|
|
|
511
521
|
_logger.debug(f"Execution trace file being reset: "
|
|
512
522
|
f"{self.execution_trace_filepath} to be closed ...")
|
|
513
523
|
# Write exit command.
|
|
514
|
-
self.trace.write("EXIT\n")
|
|
524
|
+
self.trace.write(b"EXIT\n")
|
|
515
525
|
self.trace.close()
|
|
516
526
|
self.execution_trace_filepath = Path(self.execution_trace_dir, file)
|
|
517
527
|
|
|
@@ -523,12 +533,12 @@ class Amalgam:
|
|
|
523
533
|
self.execution_trace_dir, f'{file}.{counter}')
|
|
524
534
|
counter += 1
|
|
525
535
|
|
|
526
|
-
self.trace =
|
|
536
|
+
self.trace = self.execution_trace_filepath.open("wb+")
|
|
527
537
|
_logger.debug(f"New trace file: {self.execution_trace_filepath} "
|
|
528
538
|
f"opened.")
|
|
529
539
|
# Write load command used to instantiate the amalgam instance.
|
|
530
540
|
if self.load_command_log_entry is not None:
|
|
531
|
-
self.trace.write(self.load_command_log_entry + "\n")
|
|
541
|
+
self.trace.write(self.load_command_log_entry + b"\n")
|
|
532
542
|
self.trace.flush()
|
|
533
543
|
|
|
534
544
|
def __str__(self) -> str:
|
|
@@ -543,7 +553,7 @@ class Amalgam:
|
|
|
543
553
|
getattr(self, 'trace', None) is not None
|
|
544
554
|
):
|
|
545
555
|
try:
|
|
546
|
-
self.trace.write("EXIT\n")
|
|
556
|
+
self.trace.write(b"EXIT\n")
|
|
547
557
|
except Exception: # noqa - deliberately broad
|
|
548
558
|
pass
|
|
549
559
|
|
|
@@ -559,7 +569,7 @@ class Amalgam:
|
|
|
559
569
|
The raw reply string to log.
|
|
560
570
|
"""
|
|
561
571
|
if self.trace:
|
|
562
|
-
self.trace.write("# NOTE >" +
|
|
572
|
+
self.trace.write(b"# NOTE >" + comment.encode() + b"\n")
|
|
563
573
|
self.trace.flush()
|
|
564
574
|
|
|
565
575
|
def _log_reply(self, reply: t.Any):
|
|
@@ -574,7 +584,13 @@ class Amalgam:
|
|
|
574
584
|
The raw reply string to log.
|
|
575
585
|
"""
|
|
576
586
|
if self.trace:
|
|
577
|
-
|
|
587
|
+
if isinstance(reply, ResultWithLog):
|
|
588
|
+
if reply.json:
|
|
589
|
+
self.trace.write(b"# RESULT >" + reply.json + b"\n")
|
|
590
|
+
if reply.log:
|
|
591
|
+
self.trace.write(b"# LOG >" + reply.log + b"\n")
|
|
592
|
+
else:
|
|
593
|
+
self.trace.write(b"# RESULT >" + str(reply).encode() + b"\n")
|
|
578
594
|
self.trace.flush()
|
|
579
595
|
|
|
580
596
|
def _log_time(self, label: str):
|
|
@@ -588,11 +604,11 @@ class Amalgam:
|
|
|
588
604
|
"""
|
|
589
605
|
if self.trace:
|
|
590
606
|
dt = datetime.now()
|
|
591
|
-
|
|
592
|
-
|
|
607
|
+
time_str = f"{label} {dt:%Y-%m-%d %H:%M:%S},{f'{dt:%f}'[:3]}"
|
|
608
|
+
self.trace.write(b"# TIME " + time_str.encode() + b"\n")
|
|
593
609
|
self.trace.flush()
|
|
594
610
|
|
|
595
|
-
def _log_execution(self, execution_string:
|
|
611
|
+
def _log_execution(self, execution_string: bytes):
|
|
596
612
|
"""
|
|
597
613
|
Log an execution string.
|
|
598
614
|
|
|
@@ -601,7 +617,7 @@ class Amalgam:
|
|
|
601
617
|
|
|
602
618
|
Parameters
|
|
603
619
|
----------
|
|
604
|
-
execution_string :
|
|
620
|
+
execution_string : bytes
|
|
605
621
|
A formatted string that can be piped into an amalgam command line
|
|
606
622
|
process for use in debugging.
|
|
607
623
|
|
|
@@ -610,9 +626,35 @@ class Amalgam:
|
|
|
610
626
|
string passed is valid.
|
|
611
627
|
"""
|
|
612
628
|
if self.trace:
|
|
613
|
-
self.trace.write(execution_string + "\n")
|
|
629
|
+
self.trace.write(execution_string + b"\n")
|
|
614
630
|
self.trace.flush()
|
|
615
631
|
|
|
632
|
+
def _log_execution_std(self, command: bytes, *args: str, suffix: str | bytes | None = None) -> None:
|
|
633
|
+
"""
|
|
634
|
+
Log an execution string in a canonical form.
|
|
635
|
+
|
|
636
|
+
This looks like ``COMMAND "arg" "arg" suffix``.
|
|
637
|
+
|
|
638
|
+
Parameters
|
|
639
|
+
----------
|
|
640
|
+
command : bytes
|
|
641
|
+
The trace file command string.
|
|
642
|
+
args : str
|
|
643
|
+
Arbitrary parameters to the command, will have double quotes escaped.
|
|
644
|
+
suffix : bytes, optional
|
|
645
|
+
Arbitrary binary data to append to the command string unprocessed.
|
|
646
|
+
"""
|
|
647
|
+
if not self.trace:
|
|
648
|
+
return
|
|
649
|
+
words = [b"\"" + self.escape_double_quotes(arg).encode() + b"\"" for arg in args]
|
|
650
|
+
words.insert(0, command)
|
|
651
|
+
if isinstance(suffix, str):
|
|
652
|
+
words.append(suffix.encode())
|
|
653
|
+
elif isinstance(suffix, bytes):
|
|
654
|
+
words.append(suffix)
|
|
655
|
+
self.trace.write(b" ".join(words) + b"\n")
|
|
656
|
+
self.trace.flush()
|
|
657
|
+
|
|
616
658
|
def gc(self):
|
|
617
659
|
"""Force garbage collection when called if self.force_gc is set."""
|
|
618
660
|
if (
|
|
@@ -720,10 +762,7 @@ class Amalgam:
|
|
|
720
762
|
handle_buf = self.str_to_char_p(handle)
|
|
721
763
|
label_buf = self.str_to_char_p(label)
|
|
722
764
|
|
|
723
|
-
self.
|
|
724
|
-
f"GET_JSON_FROM_LABEL \"{self.escape_double_quotes(handle)}\" "
|
|
725
|
-
f"\"{self.escape_double_quotes(label)}\""
|
|
726
|
-
))
|
|
765
|
+
self._log_execution_std(b"GET_JSON_FROM_LABEL", handle, label)
|
|
727
766
|
result = self.char_p_to_bytes(self.amlg.GetJSONPtrFromLabel(handle_buf, label_buf))
|
|
728
767
|
self._log_reply(result)
|
|
729
768
|
|
|
@@ -757,11 +796,7 @@ class Amalgam:
|
|
|
757
796
|
label_buf = self.str_to_char_p(label)
|
|
758
797
|
json_buf = self.str_to_char_p(json)
|
|
759
798
|
|
|
760
|
-
self.
|
|
761
|
-
f"SET_JSON_TO_LABEL \"{self.escape_double_quotes(handle)}\" "
|
|
762
|
-
f"\"{self.escape_double_quotes(label)}\" "
|
|
763
|
-
f"{json}"
|
|
764
|
-
))
|
|
799
|
+
self._log_execution_std(b"SET_JSON_TO_LABEL", handle, label, suffix=json)
|
|
765
800
|
self.amlg.SetJSONToLabel(handle_buf, label_buf, json_buf)
|
|
766
801
|
self._log_reply(None)
|
|
767
802
|
|
|
@@ -779,7 +814,8 @@ class Amalgam:
|
|
|
779
814
|
persist: bool = False,
|
|
780
815
|
json_file_params: str = "",
|
|
781
816
|
write_log: str = "",
|
|
782
|
-
print_log: str = ""
|
|
817
|
+
print_log: str = "",
|
|
818
|
+
entity_path: list[str] | None = None,
|
|
783
819
|
) -> LoadEntityStatus:
|
|
784
820
|
"""
|
|
785
821
|
Load an entity from an amalgam source file.
|
|
@@ -805,6 +841,9 @@ class Amalgam:
|
|
|
805
841
|
print_log : str, default ""
|
|
806
842
|
Path to the print log. If empty string, the print log is
|
|
807
843
|
not generated.
|
|
844
|
+
entity_path: list[str], optional
|
|
845
|
+
If provided and non-empty, load the content into an entity
|
|
846
|
+
contained within `handle` at this path.
|
|
808
847
|
|
|
809
848
|
Returns
|
|
810
849
|
-------
|
|
@@ -812,7 +851,8 @@ class Amalgam:
|
|
|
812
851
|
Status of LoadEntity call.
|
|
813
852
|
"""
|
|
814
853
|
self.amlg.LoadEntity.argtypes = [
|
|
815
|
-
c_char_p, c_char_p, c_char_p, c_bool, c_char_p, c_char_p, c_char_p
|
|
854
|
+
c_char_p, c_char_p, c_char_p, c_bool, c_char_p, c_char_p, c_char_p, POINTER(c_char_p),
|
|
855
|
+
c_size_t]
|
|
816
856
|
self.amlg.LoadEntity.restype = _LoadEntityStatus
|
|
817
857
|
handle_buf = self.str_to_char_p(handle)
|
|
818
858
|
file_path_buf = self.str_to_char_p(file_path)
|
|
@@ -820,18 +860,26 @@ class Amalgam:
|
|
|
820
860
|
json_file_params_buf = self.str_to_char_p(json_file_params)
|
|
821
861
|
write_log_buf = self.str_to_char_p(write_log)
|
|
822
862
|
print_log_buf = self.str_to_char_p(print_log)
|
|
863
|
+
entity_path_p = None
|
|
864
|
+
entity_path_len = 0
|
|
823
865
|
|
|
824
|
-
|
|
866
|
+
if entity_path is not None and len(entity_path) > 0:
|
|
867
|
+
entity_path_len = len(entity_path)
|
|
868
|
+
entity_path_p = (c_char_p * entity_path_len)()
|
|
869
|
+
for i, entry in enumerate(entity_path):
|
|
870
|
+
entity_path_p[i] = cast(self.str_to_char_p(entry), c_char_p)
|
|
871
|
+
|
|
872
|
+
self.load_command_log_entry = (
|
|
825
873
|
f"LOAD_ENTITY \"{self.escape_double_quotes(handle)}\" "
|
|
826
874
|
f"\"{self.escape_double_quotes(file_path)}\" "
|
|
827
875
|
f"\"{self.escape_double_quotes(file_type)}\" {str(persist).lower()} "
|
|
828
876
|
f"{json_lib.dumps(json_file_params)} "
|
|
829
|
-
f"\"{write_log}\" \"{print_log}\""
|
|
830
|
-
)
|
|
831
|
-
self._log_execution(load_command_log_entry)
|
|
877
|
+
f"\"{write_log}\" \"{print_log}\" \"\" \"{' '.join(entity_path or [])}\""
|
|
878
|
+
).encode()
|
|
879
|
+
self._log_execution(self.load_command_log_entry)
|
|
832
880
|
result = LoadEntityStatus(self, self.amlg.LoadEntity(
|
|
833
881
|
handle_buf, file_path_buf, file_type_buf, persist,
|
|
834
|
-
json_file_params_buf, write_log_buf, print_log_buf))
|
|
882
|
+
json_file_params_buf, write_log_buf, print_log_buf, entity_path_p, entity_path_len))
|
|
835
883
|
self._log_reply(result)
|
|
836
884
|
|
|
837
885
|
del handle_buf
|
|
@@ -840,6 +888,98 @@ class Amalgam:
|
|
|
840
888
|
del json_file_params_buf
|
|
841
889
|
del write_log_buf
|
|
842
890
|
del print_log_buf
|
|
891
|
+
if entity_path_p is not None:
|
|
892
|
+
for i in range(entity_path_len):
|
|
893
|
+
entry_buf = entity_path_p[i]
|
|
894
|
+
del entry_buf
|
|
895
|
+
del entity_path_p
|
|
896
|
+
self.gc()
|
|
897
|
+
|
|
898
|
+
return result
|
|
899
|
+
|
|
900
|
+
def load_entity_from_memory(
|
|
901
|
+
self,
|
|
902
|
+
handle: str,
|
|
903
|
+
contents: bytes,
|
|
904
|
+
*,
|
|
905
|
+
file_type: str,
|
|
906
|
+
json_file_params: str = "",
|
|
907
|
+
write_log: str = "",
|
|
908
|
+
print_log: str = "",
|
|
909
|
+
entity_path: list[str] | None = None,
|
|
910
|
+
) -> LoadEntityStatus:
|
|
911
|
+
"""
|
|
912
|
+
Load an entity from an in-memory buffer.
|
|
913
|
+
|
|
914
|
+
Parameters
|
|
915
|
+
----------
|
|
916
|
+
handle : str
|
|
917
|
+
The handle to assign the entity.
|
|
918
|
+
contents : bytes
|
|
919
|
+
The content to load.
|
|
920
|
+
file_type : str
|
|
921
|
+
The type of file to store, typically ``"amlg"`` for plain-text Amalgam or ``"caml"``
|
|
922
|
+
for binary compressed Amalgam.
|
|
923
|
+
json_file_params : str, default ""
|
|
924
|
+
Either empty string or a string of json specifying a set of key-value pairs
|
|
925
|
+
which are parameters specific to the file type. See Amalgam documentation
|
|
926
|
+
for details of allowed parameters.
|
|
927
|
+
write_log : str, default ""
|
|
928
|
+
Path to the write log. If empty string, the write log is
|
|
929
|
+
not generated.
|
|
930
|
+
print_log : str, default ""
|
|
931
|
+
Path to the print log. If empty string, the print log is
|
|
932
|
+
not generated.
|
|
933
|
+
entity_path: list[str], optional
|
|
934
|
+
If provided and non-empty, load the content into an entity
|
|
935
|
+
contained within `handle` at this path.
|
|
936
|
+
|
|
937
|
+
Returns
|
|
938
|
+
-------
|
|
939
|
+
LoadEntityStatus
|
|
940
|
+
Status of LoadEntity call.
|
|
941
|
+
"""
|
|
942
|
+
self.amlg.LoadEntityFromMemory.argtypes = [
|
|
943
|
+
c_char_p, c_void_p, c_size_t, c_char_p, c_bool, c_char_p, c_char_p, c_char_p, POINTER(c_char_p),
|
|
944
|
+
c_size_t]
|
|
945
|
+
self.amlg.LoadEntityFromMemory.restype = _LoadEntityStatus
|
|
946
|
+
handle_buf = self.str_to_char_p(handle)
|
|
947
|
+
file_type_buf = self.str_to_char_p(file_type)
|
|
948
|
+
json_file_params_buf = self.str_to_char_p(json_file_params)
|
|
949
|
+
write_log_buf = self.str_to_char_p(write_log)
|
|
950
|
+
print_log_buf = self.str_to_char_p(print_log)
|
|
951
|
+
entity_path_p = None
|
|
952
|
+
entity_path_len = 0
|
|
953
|
+
|
|
954
|
+
if entity_path is not None and len(entity_path) > 0:
|
|
955
|
+
entity_path_len = len(entity_path)
|
|
956
|
+
entity_path_p = (c_char_p * entity_path_len)()
|
|
957
|
+
for i, entry in enumerate(entity_path):
|
|
958
|
+
entity_path_p[i] = cast(self.str_to_char_p(entry), c_char_p)
|
|
959
|
+
|
|
960
|
+
self.load_command_log_entry = (
|
|
961
|
+
f"LOAD_ENTITY_FROM_MEMORY \"{self.escape_double_quotes(handle)}\" "
|
|
962
|
+
f"\"{b64encode(contents).decode()}\" "
|
|
963
|
+
f"\"{self.escape_double_quotes(file_type)}\" false "
|
|
964
|
+
f"{json_lib.dumps(json_file_params)} "
|
|
965
|
+
f"\"{write_log}\" \"{print_log}\" \"\" \"{' '.join(entity_path or [])}\""
|
|
966
|
+
).encode()
|
|
967
|
+
self._log_execution(self.load_command_log_entry)
|
|
968
|
+
result = LoadEntityStatus(self, self.amlg.LoadEntityFromMemory(
|
|
969
|
+
handle_buf, contents, len(contents), file_type_buf, False,
|
|
970
|
+
json_file_params_buf, write_log_buf, print_log_buf, entity_path_p, entity_path_len))
|
|
971
|
+
self._log_reply(result)
|
|
972
|
+
|
|
973
|
+
del handle_buf
|
|
974
|
+
del file_type_buf
|
|
975
|
+
del json_file_params_buf
|
|
976
|
+
del write_log_buf
|
|
977
|
+
del print_log_buf
|
|
978
|
+
if entity_path_p is not None:
|
|
979
|
+
for i in range(entity_path_len):
|
|
980
|
+
entry_buf = entity_path_p[i]
|
|
981
|
+
del entry_buf
|
|
982
|
+
del entity_path_p
|
|
843
983
|
self.gc()
|
|
844
984
|
|
|
845
985
|
return result
|
|
@@ -865,7 +1005,7 @@ class Amalgam:
|
|
|
865
1005
|
self.amlg.VerifyEntity.restype = _LoadEntityStatus
|
|
866
1006
|
file_path_buf = self.str_to_char_p(file_path)
|
|
867
1007
|
|
|
868
|
-
self.
|
|
1008
|
+
self._log_execution_std(b"VERIFY_ENTITY", file_path)
|
|
869
1009
|
result = LoadEntityStatus(self, self.amlg.VerifyEntity(file_path_buf))
|
|
870
1010
|
self._log_reply(result)
|
|
871
1011
|
|
|
@@ -895,7 +1035,7 @@ class Amalgam:
|
|
|
895
1035
|
self.amlg.GetEntityPermissions.restype = POINTER(c_char)
|
|
896
1036
|
handle_buf = self.str_to_char_p(handle)
|
|
897
1037
|
|
|
898
|
-
self.
|
|
1038
|
+
self._log_execution_std(b"GET_ENTITY_PERMISSIONS", handle)
|
|
899
1039
|
result = self.char_p_to_bytes(self.amlg.GetEntityPermissions(handle_buf))
|
|
900
1040
|
self._log_reply(result)
|
|
901
1041
|
|
|
@@ -931,11 +1071,7 @@ class Amalgam:
|
|
|
931
1071
|
handle_buf = self.str_to_char_p(handle)
|
|
932
1072
|
json_permissions_buf = self.str_to_char_p(json_permissions)
|
|
933
1073
|
|
|
934
|
-
|
|
935
|
-
f"SET_ENTITY_PERMISSIONS \"{self.escape_double_quotes(handle)}\" "
|
|
936
|
-
f"{json_permissions}"
|
|
937
|
-
)
|
|
938
|
-
self._log_execution(set_permissions_log_entry)
|
|
1074
|
+
self._log_execution_std(b"SET_ENTITY_PERMISSIONS", handle, suffix=json_permissions)
|
|
939
1075
|
result = self.amlg.SetEntityPermissions(handle_buf, json_permissions_buf)
|
|
940
1076
|
self._log_reply(result)
|
|
941
1077
|
|
|
@@ -999,15 +1135,13 @@ class Amalgam:
|
|
|
999
1135
|
write_log_buf = self.str_to_char_p(write_log)
|
|
1000
1136
|
print_log_buf = self.str_to_char_p(print_log)
|
|
1001
1137
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
f"\"{write_log}\" \"{print_log}\""
|
|
1138
|
+
self._log_execution_std(b"CLONE_ENTITY", handle, clone_handle, file_path, file_type,
|
|
1139
|
+
suffix=(
|
|
1140
|
+
f"{str(persist).lower()} "
|
|
1141
|
+
f"{json_lib.dumps(json_file_params)} "
|
|
1142
|
+
f"\"{write_log}\" \"{print_log}\""
|
|
1143
|
+
)
|
|
1009
1144
|
)
|
|
1010
|
-
self._log_execution(clone_command_log_entry)
|
|
1011
1145
|
result = self.amlg.CloneEntity(
|
|
1012
1146
|
handle_buf, clone_handle_buf, file_path_buf, file_type_buf, persist,
|
|
1013
1147
|
json_file_params_buf, write_log_buf, print_log_buf)
|
|
@@ -1032,7 +1166,8 @@ class Amalgam:
|
|
|
1032
1166
|
file_type: str = "",
|
|
1033
1167
|
persist: bool = False,
|
|
1034
1168
|
json_file_params: str = "",
|
|
1035
|
-
|
|
1169
|
+
entity_path: list[str] | None = None,
|
|
1170
|
+
) -> bool:
|
|
1036
1171
|
"""
|
|
1037
1172
|
Store entity to the file type specified within file_path.
|
|
1038
1173
|
|
|
@@ -1051,30 +1186,122 @@ class Amalgam:
|
|
|
1051
1186
|
Either empty string or a string of json specifying a set of key-value pairs
|
|
1052
1187
|
which are parameters specific to the file type. See Amalgam documentation
|
|
1053
1188
|
for details of allowed parameters.
|
|
1189
|
+
entity_path: list[str], optional
|
|
1190
|
+
If provided and non-empty, store the content from an entity
|
|
1191
|
+
contained within `handle` at this path.
|
|
1192
|
+
|
|
1193
|
+
Returns
|
|
1194
|
+
-------
|
|
1195
|
+
bool
|
|
1196
|
+
True if the entity file was saved successfully, False otherwise.
|
|
1054
1197
|
"""
|
|
1055
1198
|
self.amlg.StoreEntity.argtypes = [
|
|
1056
|
-
c_char_p, c_char_p, c_char_p, c_bool, c_char_p]
|
|
1199
|
+
c_char_p, c_char_p, c_char_p, c_bool, c_char_p, POINTER(c_char_p), c_size_t]
|
|
1200
|
+
self.amlg.StoreEntity.restype = c_bool
|
|
1057
1201
|
handle_buf = self.str_to_char_p(handle)
|
|
1058
1202
|
file_path_buf = self.str_to_char_p(file_path)
|
|
1059
1203
|
file_type_buf = self.str_to_char_p(file_type)
|
|
1060
1204
|
json_file_params_buf = self.str_to_char_p(json_file_params)
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1205
|
+
entity_path_p = None
|
|
1206
|
+
entity_path_len = 0
|
|
1207
|
+
|
|
1208
|
+
if entity_path is not None and len(entity_path) > 0:
|
|
1209
|
+
entity_path_len = len(entity_path)
|
|
1210
|
+
entity_path_p = (c_char_p * entity_path_len)()
|
|
1211
|
+
for i, entry in enumerate(entity_path):
|
|
1212
|
+
entity_path_p[i] = self.str_to_char_p(entry)
|
|
1213
|
+
|
|
1214
|
+
self._log_execution_std(b"STORE_ENTITY", handle, file_path, file_type,
|
|
1215
|
+
suffix=f"{str(persist).lower()} {json_lib.dumps(json_file_params)} \"{' '.join(entity_path or [])}\"")
|
|
1216
|
+
result = self.amlg.StoreEntity(
|
|
1217
|
+
handle_buf, file_path_buf, file_type_buf, persist, json_file_params_buf, entity_path_p, entity_path_len)
|
|
1218
|
+
self._log_reply(result)
|
|
1072
1219
|
|
|
1073
1220
|
del handle_buf
|
|
1074
1221
|
del file_path_buf
|
|
1075
1222
|
del file_type_buf
|
|
1076
1223
|
del json_file_params_buf
|
|
1224
|
+
if entity_path_p is not None:
|
|
1225
|
+
for i in range(entity_path_len):
|
|
1226
|
+
entry_buf = entity_path_p[i]
|
|
1227
|
+
del entry_buf
|
|
1228
|
+
del entity_path_p
|
|
1229
|
+
self.gc()
|
|
1230
|
+
return result
|
|
1231
|
+
|
|
1232
|
+
def store_entity_to_memory(
|
|
1233
|
+
self,
|
|
1234
|
+
handle: str,
|
|
1235
|
+
*,
|
|
1236
|
+
file_type: str,
|
|
1237
|
+
json_file_params: str = "",
|
|
1238
|
+
entity_path: list[str] | None = None,
|
|
1239
|
+
) -> bytes | None:
|
|
1240
|
+
"""
|
|
1241
|
+
Store entity to memory as a bytes object.
|
|
1242
|
+
|
|
1243
|
+
Parameters
|
|
1244
|
+
----------
|
|
1245
|
+
handle : str
|
|
1246
|
+
The handle of the amalgam entity.
|
|
1247
|
+
file_type : str
|
|
1248
|
+
The type of file to store, typically ``"amlg"`` for plain-text Amalgam or ``"caml"``
|
|
1249
|
+
for binary compressed Amalgam.
|
|
1250
|
+
json_file_params : str, default ""
|
|
1251
|
+
Either empty string or a string of json specifying a set of key-value pairs
|
|
1252
|
+
which are parameters specific to the file type. See Amalgam documentation
|
|
1253
|
+
for details of allowed parameters.
|
|
1254
|
+
entity_path: list[str], optional
|
|
1255
|
+
If provided and non-empty, store the content from an entity
|
|
1256
|
+
contained within `handle` at this path.
|
|
1257
|
+
|
|
1258
|
+
Returns
|
|
1259
|
+
-------
|
|
1260
|
+
bytes | None
|
|
1261
|
+
The serialized entity contents, or None on an error.
|
|
1262
|
+
"""
|
|
1263
|
+
self.amlg.StoreEntityToMemory.argtypes = [
|
|
1264
|
+
c_char_p, POINTER(c_void_p), POINTER(c_size_t), c_char_p, c_bool, c_char_p, POINTER(c_char_p), c_size_t]
|
|
1265
|
+
self.amlg.StoreEntityToMemory.restype = c_bool
|
|
1266
|
+
handle_buf = self.str_to_char_p(handle)
|
|
1267
|
+
data_p = c_void_p(None)
|
|
1268
|
+
data_len = c_size_t(0)
|
|
1269
|
+
file_type_buf = self.str_to_char_p(file_type)
|
|
1270
|
+
json_file_params_buf = self.str_to_char_p(json_file_params)
|
|
1271
|
+
entity_path_p = None
|
|
1272
|
+
entity_path_len = 0
|
|
1273
|
+
|
|
1274
|
+
if entity_path is not None and len(entity_path) > 0:
|
|
1275
|
+
entity_path_len = len(entity_path)
|
|
1276
|
+
entity_path_p = (c_char_p * entity_path_len)()
|
|
1277
|
+
for i, entry in enumerate(entity_path):
|
|
1278
|
+
entity_path_p[i] = self.str_to_char_p(entry)
|
|
1279
|
+
|
|
1280
|
+
self._log_execution_std(b"STORE_ENTITY_TO_MEMORY", handle, file_type,
|
|
1281
|
+
suffix=f"false {json_lib.dumps(json_file_params)} \"{' '.join(entity_path or [])}\"")
|
|
1282
|
+
self.amlg.StoreEntityToMemory(
|
|
1283
|
+
handle_buf, byref(data_p), byref(data_len), file_type_buf, False, json_file_params_buf, entity_path_p, entity_path_len)
|
|
1284
|
+
|
|
1285
|
+
result = None
|
|
1286
|
+
if data_p.value is not None:
|
|
1287
|
+
result = string_at(data_p.value, data_len.value)
|
|
1288
|
+
self.amlg.DeleteString.argtypes = [c_char_p]
|
|
1289
|
+
self.amlg.DeleteString.restype = None
|
|
1290
|
+
self.amlg.DeleteString(cast(data_p, c_char_p))
|
|
1291
|
+
self._log_reply(b64encode(result).decode())
|
|
1292
|
+
else:
|
|
1293
|
+
self._log_reply(None)
|
|
1294
|
+
|
|
1295
|
+
del handle_buf
|
|
1296
|
+
del file_type_buf
|
|
1297
|
+
del json_file_params_buf
|
|
1298
|
+
if entity_path_p is not None:
|
|
1299
|
+
for i in range(entity_path_len):
|
|
1300
|
+
entry_buf = entity_path_p[i]
|
|
1301
|
+
del entry_buf
|
|
1302
|
+
del entity_path_p
|
|
1077
1303
|
self.gc()
|
|
1304
|
+
return result
|
|
1078
1305
|
|
|
1079
1306
|
def destroy_entity(
|
|
1080
1307
|
self,
|
|
@@ -1091,7 +1318,7 @@ class Amalgam:
|
|
|
1091
1318
|
self.amlg.DestroyEntity.argtypes = [c_char_p]
|
|
1092
1319
|
handle_buf = self.str_to_char_p(handle)
|
|
1093
1320
|
|
|
1094
|
-
self.
|
|
1321
|
+
self._log_execution_std(b"DESTROY_ENTITY", handle)
|
|
1095
1322
|
self.amlg.DestroyEntity(handle_buf)
|
|
1096
1323
|
self._log_reply(None)
|
|
1097
1324
|
|
|
@@ -1124,8 +1351,7 @@ class Amalgam:
|
|
|
1124
1351
|
handle_buf = self.str_to_char_p(handle)
|
|
1125
1352
|
rand_seed_buf = self.str_to_char_p(rand_seed)
|
|
1126
1353
|
|
|
1127
|
-
self.
|
|
1128
|
-
f'"{self.escape_double_quotes(rand_seed)}"')
|
|
1354
|
+
self._log_execution_std(b"SET_RANDOM_SEED", handle, rand_seed)
|
|
1129
1355
|
result = self.amlg.SetRandomSeed(handle_buf, rand_seed_buf)
|
|
1130
1356
|
self._log_reply(None)
|
|
1131
1357
|
|
|
@@ -1186,12 +1412,7 @@ class Amalgam:
|
|
|
1186
1412
|
json_buf = self.str_to_char_p(json)
|
|
1187
1413
|
|
|
1188
1414
|
self._log_time("EXECUTION START")
|
|
1189
|
-
self.
|
|
1190
|
-
"EXECUTE_ENTITY_JSON "
|
|
1191
|
-
f"\"{self.escape_double_quotes(handle)}\" "
|
|
1192
|
-
f"\"{self.escape_double_quotes(label)}\" "
|
|
1193
|
-
f"{json}"
|
|
1194
|
-
))
|
|
1415
|
+
self._log_execution_std(b"EXECUTE_ENTITY_JSON", handle, label, suffix=json)
|
|
1195
1416
|
result = self.char_p_to_bytes(self.amlg.ExecuteEntityJsonPtr(
|
|
1196
1417
|
handle_buf, label_buf, json_buf))
|
|
1197
1418
|
self._log_time("EXECUTION STOP")
|
|
@@ -1236,12 +1457,7 @@ class Amalgam:
|
|
|
1236
1457
|
json_buf = self.str_to_char_p(json)
|
|
1237
1458
|
|
|
1238
1459
|
self._log_time("EXECUTION START")
|
|
1239
|
-
self.
|
|
1240
|
-
"EXECUTE_ENTITY_JSON_LOGGED "
|
|
1241
|
-
f"\"{self.escape_double_quotes(handle)}\" "
|
|
1242
|
-
f"\"{self.escape_double_quotes(label)}\" "
|
|
1243
|
-
f"{json}"
|
|
1244
|
-
))
|
|
1460
|
+
self._log_execution_std(b"EXECUTE_ENTITY_JSON_LOGGED", handle, label, suffix=json)
|
|
1245
1461
|
result = ResultWithLog.from_c_result(self, self.amlg.ExecuteEntityJsonPtrLogged(
|
|
1246
1462
|
handle_buf, label_buf, json_buf))
|
|
1247
1463
|
self._log_time("EXECUTION STOP")
|
|
@@ -1256,7 +1472,7 @@ class Amalgam:
|
|
|
1256
1472
|
def eval_on_entity(
|
|
1257
1473
|
self,
|
|
1258
1474
|
handle: str,
|
|
1259
|
-
amlg: str
|
|
1475
|
+
amlg: str | bytes
|
|
1260
1476
|
) -> bytes:
|
|
1261
1477
|
"""
|
|
1262
1478
|
Execute arbitrary Amalgam code against an entity.
|
|
@@ -1265,7 +1481,7 @@ class Amalgam:
|
|
|
1265
1481
|
----------
|
|
1266
1482
|
handle : str
|
|
1267
1483
|
The handle of the amalgam entity.
|
|
1268
|
-
amlg : str
|
|
1484
|
+
amlg : str | bytes
|
|
1269
1485
|
The code to execute.
|
|
1270
1486
|
|
|
1271
1487
|
Returns
|
|
@@ -1281,11 +1497,7 @@ class Amalgam:
|
|
|
1281
1497
|
amlg_buf = self.str_to_char_p(amlg)
|
|
1282
1498
|
|
|
1283
1499
|
self._log_time("EXECUTION START")
|
|
1284
|
-
self.
|
|
1285
|
-
"EVAL_ON_ENTITY "
|
|
1286
|
-
f"\"{self.escape_double_quotes(handle)}\" "
|
|
1287
|
-
f"\"{self.escape_double_quotes(amlg)}\""
|
|
1288
|
-
))
|
|
1500
|
+
self._log_execution_std(b"EVAL_ON_ENTITY", handle, str(amlg))
|
|
1289
1501
|
result = self.char_p_to_bytes(self.amlg.EvalOnEntity(
|
|
1290
1502
|
handle_buf, amlg_buf))
|
|
1291
1503
|
self._log_time("EXECUTION STOP")
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
amalgam/lib/version.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": {
|
|
3
|
-
"amalgam": "
|
|
4
|
-
"amalgam_sha": "
|
|
5
|
-
"amalgam_url": "https://github.com/howsoai/amalgam/releases/tag/
|
|
3
|
+
"amalgam": "71.0.0",
|
|
4
|
+
"amalgam_sha": "9a65d4226a5166e9e3968057a603287096fa7005",
|
|
5
|
+
"amalgam_url": "https://github.com/howsoai/amalgam/releases/tag/71.0.0",
|
|
6
6
|
"amalgam_build_date": "",
|
|
7
7
|
"amalgam_display_title": ""
|
|
8
8
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: amalgam-lang
|
|
3
|
-
Version:
|
|
3
|
+
Version: 25.2.5
|
|
4
4
|
Summary: A direct interface with Amalgam compiled DLL, dylib, or so.
|
|
5
5
|
Author: Howso Incorporated
|
|
6
6
|
Author-email: support@howso.com
|
|
@@ -675,7 +675,6 @@ Classifier: Intended Audience :: Science/Research
|
|
|
675
675
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
676
676
|
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
|
|
677
677
|
Classifier: Programming Language :: Python :: 3
|
|
678
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
679
678
|
Classifier: Programming Language :: Python :: 3.10
|
|
680
679
|
Classifier: Programming Language :: Python :: 3.11
|
|
681
680
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -686,7 +685,7 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
686
685
|
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
|
|
687
686
|
Classifier: Operating System :: Microsoft :: Windows :: Windows 11
|
|
688
687
|
Classifier: Operating System :: POSIX :: Linux
|
|
689
|
-
Requires-Python: >=3.
|
|
688
|
+
Requires-Python: >=3.10
|
|
690
689
|
Description-Content-Type: text/markdown
|
|
691
690
|
License-File: LICENSE.txt
|
|
692
691
|
Provides-Extra: dev
|
|
@@ -714,7 +713,7 @@ Coding in [Amalgam](https://github.com/howsoai/amalgam) can be done natively as
|
|
|
714
713
|
|
|
715
714
|
## Supported Platforms
|
|
716
715
|
|
|
717
|
-
Compatible with Python versions: 3.
|
|
716
|
+
Compatible with Python versions: 3.10, 3.11, 3.12, and 3.13.
|
|
718
717
|
|
|
719
718
|
#### Operating Systems
|
|
720
719
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
amalgam/__init__.py,sha256=oHu7Zr4eGDUqj93pLwz8t7gLa8lpAx6Q-xbGiJ3nJx0,18
|
|
2
|
+
amalgam/api.py,sha256=2LeiTkl6FLdd-MDDHjkWAl7vLOnI3eUXF1FeV9fEkGQ,53792
|
|
3
|
+
amalgam/lib/version.json,sha256=KLIEcoEJPWvPnfdbzhK0grsTolOYwMz_29lG2g-qcas,250
|
|
4
|
+
amalgam/lib/darwin/arm64/amalgam-mt.dylib,sha256=8XphNYzG6P31ZviKFc_8NEudhf1T3B-7vmuinM77lh4,3362896
|
|
5
|
+
amalgam/lib/darwin/arm64/amalgam-omp.dylib,sha256=La4iFFCNoyplm64Ps5EEiVt8fnEmOYDA-emB2RVQsBk,3700560
|
|
6
|
+
amalgam/lib/darwin/arm64/amalgam-st.dylib,sha256=Hsu5IeZBCnk-8b6ozrkMUXkeW-VNVEDQ4UO8b8tnvI0,3144768
|
|
7
|
+
amalgam/lib/darwin/arm64/docs/version.json,sha256=DGQGMrgbSvJpyyK_YIzD8RF4xP8dAjQgiIsJ3sWHv3w,25
|
|
8
|
+
amalgam_lang-25.2.5.dist-info/licenses/LICENSE.txt,sha256=2xqHuoHohba7gpcZZKtOICRjzeKsQANXG8WoV9V35KM,33893
|
|
9
|
+
amalgam_lang-25.2.5.dist-info/METADATA,sha256=0V6bApR_dTvfvRdqJleSkpeEeUrLxNdXSE2jzDoqwRQ,43832
|
|
10
|
+
amalgam_lang-25.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
+
amalgam_lang-25.2.5.dist-info/top_level.txt,sha256=rmPHU144SyaB25u5-FAQyECAQnJ39NvuJEcKXMRcdBo,8
|
|
12
|
+
amalgam_lang-25.2.5.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
amalgam/__init__.py,sha256=oHu7Zr4eGDUqj93pLwz8t7gLa8lpAx6Q-xbGiJ3nJx0,18
|
|
2
|
-
amalgam/api.py,sha256=zS2h1oKrNmXNERicQt6dcpjrOQ9XVm5PTf37AIDlMTI,44799
|
|
3
|
-
amalgam/lib/version.json,sha256=W2qXXdNREbzHXVO0UKN4ajwB-IFPwD5DNKlzgGpmGK0,250
|
|
4
|
-
amalgam/lib/darwin/arm64/amalgam-mt.dylib,sha256=9qVrSakUqC11nGbfSR3SuZVArDKfz3PaGmpHIcYLK0w,2951696
|
|
5
|
-
amalgam/lib/darwin/arm64/amalgam-omp.dylib,sha256=eRAzV9wSZCrTgwV1j1e1DPFN5675RMwGJx397HZH-qE,3313728
|
|
6
|
-
amalgam/lib/darwin/arm64/amalgam-st.dylib,sha256=y-mcPzMjfBCaQmeeNYL59dc5YDL15r5S5LcEp9Ab-GU,2783280
|
|
7
|
-
amalgam/lib/darwin/arm64/docs/version.json,sha256=Yg7pfVbtDLaoqfdzh_PyMWGT90q46seEaJ3NSDe-4QU,25
|
|
8
|
-
amalgam_lang-20.0.2.dist-info/licenses/LICENSE.txt,sha256=2xqHuoHohba7gpcZZKtOICRjzeKsQANXG8WoV9V35KM,33893
|
|
9
|
-
amalgam_lang-20.0.2.dist-info/METADATA,sha256=jML8rmgRW4YKfGGdxONHp1nqsPSr3GNiDGGZeYN7S00,43886
|
|
10
|
-
amalgam_lang-20.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
-
amalgam_lang-20.0.2.dist-info/top_level.txt,sha256=rmPHU144SyaB25u5-FAQyECAQnJ39NvuJEcKXMRcdBo,8
|
|
12
|
-
amalgam_lang-20.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|