rapydscript-ns 0.9.2 → 0.9.4
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.
- package/CHANGELOG.md +28 -0
- package/PYTHON_GAPS.md +352 -0
- package/README.md +176 -32
- package/TODO.md +1 -128
- package/bin/rapydscript +70 -70
- package/language-service/index.js +242 -11
- package/memory/project_string_impl.md +43 -0
- package/package.json +1 -1
- package/release/baselib-plain-pretty.js +248 -38
- package/release/baselib-plain-ugly.js +8 -8
- package/release/compiler.js +778 -277
- package/release/signatures.json +30 -30
- package/src/ast.pyj +10 -1
- package/src/baselib-builtins.pyj +56 -2
- package/src/baselib-containers.pyj +25 -1
- package/src/baselib-errors.pyj +7 -3
- package/src/baselib-internal.pyj +51 -6
- package/src/baselib-str.pyj +18 -5
- package/src/lib/asyncio.pyj +534 -0
- package/src/lib/base64.pyj +399 -0
- package/src/lib/bisect.pyj +73 -0
- package/src/lib/collections.pyj +228 -4
- package/src/lib/csv.pyj +494 -0
- package/src/lib/heapq.pyj +98 -0
- package/src/lib/html.pyj +382 -0
- package/src/lib/http/__init__.pyj +98 -0
- package/src/lib/http/client.pyj +304 -0
- package/src/lib/http/cookies.pyj +236 -0
- package/src/lib/logging.pyj +672 -0
- package/src/lib/pprint.pyj +455 -0
- package/src/lib/pythonize.pyj +20 -20
- package/src/lib/statistics.pyj +0 -0
- package/src/lib/string.pyj +357 -0
- package/src/lib/textwrap.pyj +329 -0
- package/src/lib/urllib/__init__.pyj +14 -0
- package/src/lib/urllib/error.pyj +66 -0
- package/src/lib/urllib/parse.pyj +475 -0
- package/src/lib/urllib/request.pyj +86 -0
- package/src/monaco-language-service/analyzer.js +5 -2
- package/src/monaco-language-service/completions.js +26 -0
- package/src/monaco-language-service/diagnostics.js +203 -4
- package/src/monaco-language-service/scope.js +1 -0
- package/src/output/codegen.pyj +4 -1
- package/src/output/functions.pyj +152 -6
- package/src/output/loops.pyj +17 -2
- package/src/output/modules.pyj +1 -1
- package/src/output/operators.pyj +15 -0
- package/src/output/stream.pyj +0 -1
- package/src/parse.pyj +108 -24
- package/src/tokenizer.pyj +19 -3
- package/test/async_generators.pyj +144 -0
- package/test/asyncio.pyj +307 -0
- package/test/base64.pyj +202 -0
- package/test/baselib.pyj +23 -0
- package/test/bisect.pyj +178 -0
- package/test/chainmap.pyj +185 -0
- package/test/csv.pyj +405 -0
- package/test/float_special.pyj +64 -0
- package/test/heapq.pyj +174 -0
- package/test/html.pyj +212 -0
- package/test/http.pyj +259 -0
- package/test/imports.pyj +79 -72
- package/test/logging.pyj +356 -0
- package/test/long.pyj +130 -0
- package/test/parenthesized_with.pyj +141 -0
- package/test/pprint.pyj +232 -0
- package/test/python_compat.pyj +3 -5
- package/test/python_modulo.pyj +76 -0
- package/test/python_modulo_off.pyj +21 -0
- package/test/statistics.pyj +224 -0
- package/test/str.pyj +14 -0
- package/test/string.pyj +245 -0
- package/test/textwrap.pyj +172 -0
- package/test/type_display.pyj +48 -0
- package/test/type_enforcement.pyj +164 -0
- package/test/unit/index.js +94 -6
- package/test/unit/language-service-completions.js +121 -0
- package/test/unit/language-service-scope.js +32 -0
- package/test/unit/language-service.js +190 -5
- package/test/unit/run-language-service.js +17 -3
- package/test/unit/web-repl.js +2401 -13
- package/test/urllib.pyj +193 -0
- package/tools/compile.js +1 -1
- package/tools/embedded_compiler.js +7 -7
- package/tools/export.js +4 -2
- package/web-repl/main.js +1 -1
- package/web-repl/rapydscript.js +7 -5
- package/test/omit_function_metadata.pyj +0 -20
package/src/lib/collections.pyj
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
# License: BSD
|
|
3
3
|
# RapydScript implementation of Python's collections standard library.
|
|
4
4
|
#
|
|
5
|
-
# Supported: namedtuple, deque, Counter, OrderedDict, defaultdict
|
|
5
|
+
# Supported: namedtuple, deque, Counter, OrderedDict, defaultdict, ChainMap
|
|
6
6
|
#
|
|
7
|
-
# Note: Counter, OrderedDict, and
|
|
8
|
-
# For Python-compatible subscript syntax (obj[key])
|
|
7
|
+
# Note: Counter, OrderedDict, defaultdict, and ChainMap use
|
|
8
|
+
# __getitem__/__setitem__. For Python-compatible subscript syntax (obj[key])
|
|
9
|
+
# in user code, add:
|
|
9
10
|
# from __python__ import overload_getitem
|
|
10
11
|
|
|
11
12
|
|
|
@@ -13,7 +14,7 @@ def namedtuple(typename, field_names):
|
|
|
13
14
|
"""Return a new class with named fields, like Python's collections.namedtuple."""
|
|
14
15
|
if isinstance(field_names, str):
|
|
15
16
|
# Use explicit JS regex split for cross-environment safety
|
|
16
|
-
fields = v"field_names.replace(/,/g, ' ').trim().split(
|
|
17
|
+
fields = v"field_names.replace(/,/g, ' ').trim().split(/\s+/).filter(function(s){return s.length>0;})"
|
|
17
18
|
else:
|
|
18
19
|
fields = list(field_names)
|
|
19
20
|
n = fields.length
|
|
@@ -693,3 +694,226 @@ class defaultdict:
|
|
|
693
694
|
if self._data[k] != src[k]:
|
|
694
695
|
return False
|
|
695
696
|
return True
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
class ChainMap:
|
|
700
|
+
"""Combine several mappings into a single, updateable view.
|
|
701
|
+
|
|
702
|
+
Lookups search the underlying mappings in order, so the first mapping
|
|
703
|
+
wins. Writes, updates, and deletions affect only the first mapping.
|
|
704
|
+
Mirrors Python's collections.ChainMap.
|
|
705
|
+
"""
|
|
706
|
+
|
|
707
|
+
def __init__(self, *maps):
|
|
708
|
+
if maps.length == 0:
|
|
709
|
+
self.maps = [{}]
|
|
710
|
+
else:
|
|
711
|
+
self.maps = list(maps)
|
|
712
|
+
|
|
713
|
+
# ── internal mapping-access helpers ───────────────────────────────────
|
|
714
|
+
# A "map" may be a plain JS object, a RapydScript dict (ρσ_dict, used for
|
|
715
|
+
# {...} literals in the web-repl), or any RapydScript mapping defining
|
|
716
|
+
# __getitem__/__setitem__/__contains__ (OrderedDict, defaultdict, Counter,
|
|
717
|
+
# or a nested ChainMap).
|
|
718
|
+
|
|
719
|
+
def _is_rdict(self, m):
|
|
720
|
+
return v'!!(m && m.jsmap && typeof m.jsmap.get === "function")'
|
|
721
|
+
|
|
722
|
+
def _is_mapping(self, m):
|
|
723
|
+
return v'!!(m && typeof m.__getitem__ === "function" && typeof m.__contains__ === "function")'
|
|
724
|
+
|
|
725
|
+
def _mkeys(self, m):
|
|
726
|
+
if self._is_rdict(m):
|
|
727
|
+
return v'Array.from(m.jsmap.keys())'
|
|
728
|
+
if self._is_mapping(m):
|
|
729
|
+
return list(m.keys())
|
|
730
|
+
return Object.keys(m)
|
|
731
|
+
|
|
732
|
+
def _mhas(self, m, key):
|
|
733
|
+
if self._is_rdict(m):
|
|
734
|
+
return v'm.jsmap.has(key)'
|
|
735
|
+
if self._is_mapping(m):
|
|
736
|
+
return m.__contains__(key)
|
|
737
|
+
return v'Object.prototype.hasOwnProperty.call(m, key)'
|
|
738
|
+
|
|
739
|
+
def _mget(self, m, key):
|
|
740
|
+
if self._is_rdict(m):
|
|
741
|
+
return v'm.jsmap.get(key)'
|
|
742
|
+
if self._is_mapping(m):
|
|
743
|
+
return m.__getitem__(key)
|
|
744
|
+
return v'm[key]'
|
|
745
|
+
|
|
746
|
+
def _mset(self, m, key, value):
|
|
747
|
+
if self._is_rdict(m):
|
|
748
|
+
v'm.jsmap.set(key, value)'
|
|
749
|
+
elif self._is_mapping(m):
|
|
750
|
+
m.__setitem__(key, value)
|
|
751
|
+
else:
|
|
752
|
+
v'm[key] = value'
|
|
753
|
+
|
|
754
|
+
def _mdel(self, m, key):
|
|
755
|
+
if self._is_rdict(m):
|
|
756
|
+
v'm.jsmap["delete"](key)'
|
|
757
|
+
elif self._is_mapping(m):
|
|
758
|
+
m.__delitem__(key)
|
|
759
|
+
else:
|
|
760
|
+
v'delete m[key]'
|
|
761
|
+
|
|
762
|
+
def _all_keys(self):
|
|
763
|
+
# Unique keys across every map. Maps are scanned last-to-first so that
|
|
764
|
+
# earlier maps keep their key positions, matching Python's iteration.
|
|
765
|
+
seen = {}
|
|
766
|
+
result = []
|
|
767
|
+
i = self.maps.length - 1
|
|
768
|
+
while i >= 0:
|
|
769
|
+
for k in self._mkeys(self.maps[i]):
|
|
770
|
+
if k not in seen:
|
|
771
|
+
seen[k] = True
|
|
772
|
+
result.push(k)
|
|
773
|
+
i -= 1
|
|
774
|
+
return result
|
|
775
|
+
|
|
776
|
+
def __getitem__(self, key):
|
|
777
|
+
for m in self.maps:
|
|
778
|
+
if self._mhas(m, key):
|
|
779
|
+
return self._mget(m, key)
|
|
780
|
+
raise KeyError(repr(key))
|
|
781
|
+
|
|
782
|
+
def __setitem__(self, key, value):
|
|
783
|
+
self._mset(self.maps[0], key, value)
|
|
784
|
+
|
|
785
|
+
def __delitem__(self, key):
|
|
786
|
+
if not self._mhas(self.maps[0], key):
|
|
787
|
+
raise KeyError('Key not found in the first mapping: ' + repr(key))
|
|
788
|
+
self._mdel(self.maps[0], key)
|
|
789
|
+
|
|
790
|
+
def __contains__(self, key):
|
|
791
|
+
for m in self.maps:
|
|
792
|
+
if self._mhas(m, key):
|
|
793
|
+
return True
|
|
794
|
+
return False
|
|
795
|
+
|
|
796
|
+
def __len__(self):
|
|
797
|
+
return self._all_keys().length
|
|
798
|
+
|
|
799
|
+
def __iter__(self):
|
|
800
|
+
return iter(self._all_keys())
|
|
801
|
+
|
|
802
|
+
def __bool__(self):
|
|
803
|
+
for m in self.maps:
|
|
804
|
+
if self._mkeys(m).length > 0:
|
|
805
|
+
return True
|
|
806
|
+
return False
|
|
807
|
+
|
|
808
|
+
def _map_repr(self, m):
|
|
809
|
+
pairs = [repr(k) + ': ' + repr(self._mget(m, k)) for k in self._mkeys(m)]
|
|
810
|
+
return '{' + pairs.join(', ') + '}'
|
|
811
|
+
|
|
812
|
+
def __repr__(self):
|
|
813
|
+
parts = [self._map_repr(m) for m in self.maps]
|
|
814
|
+
return 'ChainMap(' + parts.join(', ') + ')'
|
|
815
|
+
|
|
816
|
+
def __eq__(self, other):
|
|
817
|
+
if other is None:
|
|
818
|
+
return False
|
|
819
|
+
is_mapish = self._is_rdict(other) or self._is_mapping(other) or (jstype(other) is 'object' and not Array.isArray(other))
|
|
820
|
+
if not is_mapish:
|
|
821
|
+
return False
|
|
822
|
+
a = self._all_keys()
|
|
823
|
+
b = self._mkeys(other)
|
|
824
|
+
if a.length != b.length:
|
|
825
|
+
return False
|
|
826
|
+
for k in a:
|
|
827
|
+
if not self._mhas(other, k):
|
|
828
|
+
return False
|
|
829
|
+
if self.__getitem__(k) != self._mget(other, k):
|
|
830
|
+
return False
|
|
831
|
+
return True
|
|
832
|
+
|
|
833
|
+
def get(self, key, dflt=None):
|
|
834
|
+
if self.__contains__(key):
|
|
835
|
+
return self.__getitem__(key)
|
|
836
|
+
return dflt
|
|
837
|
+
|
|
838
|
+
def keys(self):
|
|
839
|
+
return self._all_keys()
|
|
840
|
+
|
|
841
|
+
def values(self):
|
|
842
|
+
return [self.__getitem__(k) for k in self._all_keys()]
|
|
843
|
+
|
|
844
|
+
def items(self):
|
|
845
|
+
return [[k, self.__getitem__(k)] for k in self._all_keys()]
|
|
846
|
+
|
|
847
|
+
@property
|
|
848
|
+
def parents(self):
|
|
849
|
+
cm = ChainMap()
|
|
850
|
+
cm.maps = self.maps.slice(1)
|
|
851
|
+
return cm
|
|
852
|
+
|
|
853
|
+
def new_child(self, m=None):
|
|
854
|
+
if m is None:
|
|
855
|
+
m = {}
|
|
856
|
+
cm = ChainMap()
|
|
857
|
+
cm.maps = [m].concat(self.maps)
|
|
858
|
+
return cm
|
|
859
|
+
|
|
860
|
+
def _copy_map(self, m):
|
|
861
|
+
if jstype(m.copy) is 'function':
|
|
862
|
+
return m.copy()
|
|
863
|
+
result = {}
|
|
864
|
+
for k in Object.keys(m):
|
|
865
|
+
result[k] = m[k]
|
|
866
|
+
return result
|
|
867
|
+
|
|
868
|
+
def copy(self):
|
|
869
|
+
cm = ChainMap()
|
|
870
|
+
cm.maps = [self._copy_map(self.maps[0])].concat(self.maps.slice(1))
|
|
871
|
+
return cm
|
|
872
|
+
|
|
873
|
+
def pop(self, key, *rest):
|
|
874
|
+
first = self.maps[0]
|
|
875
|
+
if self._mhas(first, key):
|
|
876
|
+
val = self._mget(first, key)
|
|
877
|
+
self._mdel(first, key)
|
|
878
|
+
return val
|
|
879
|
+
if len(rest) > 0:
|
|
880
|
+
return rest[0]
|
|
881
|
+
raise KeyError('Key not found in the first mapping: ' + repr(key))
|
|
882
|
+
|
|
883
|
+
def popitem(self):
|
|
884
|
+
first = self.maps[0]
|
|
885
|
+
keys = self._mkeys(first)
|
|
886
|
+
if keys.length == 0:
|
|
887
|
+
raise KeyError('No keys found in the first mapping.')
|
|
888
|
+
k = keys[keys.length - 1]
|
|
889
|
+
val = self._mget(first, k)
|
|
890
|
+
self._mdel(first, k)
|
|
891
|
+
return [k, val]
|
|
892
|
+
|
|
893
|
+
def setdefault(self, key, dflt=None):
|
|
894
|
+
if not self.__contains__(key):
|
|
895
|
+
self._mset(self.maps[0], key, dflt)
|
|
896
|
+
return self.__getitem__(key)
|
|
897
|
+
|
|
898
|
+
def clear(self):
|
|
899
|
+
first = self.maps[0]
|
|
900
|
+
if jstype(first.clear) is 'function':
|
|
901
|
+
first.clear()
|
|
902
|
+
else:
|
|
903
|
+
for k in Object.keys(first):
|
|
904
|
+
v'delete first[k]'
|
|
905
|
+
|
|
906
|
+
def update(self, other=None, **kwargs):
|
|
907
|
+
first = self.maps[0]
|
|
908
|
+
if other is not None:
|
|
909
|
+
if self._is_rdict(other) or self._is_mapping(other):
|
|
910
|
+
for k in self._mkeys(other):
|
|
911
|
+
self._mset(first, k, self._mget(other, k))
|
|
912
|
+
elif jstype(other) is 'object' and not Array.isArray(other):
|
|
913
|
+
for k in Object.keys(other):
|
|
914
|
+
self._mset(first, k, other[k])
|
|
915
|
+
else:
|
|
916
|
+
for pair in other:
|
|
917
|
+
self._mset(first, pair[0], pair[1])
|
|
918
|
+
for k in kwargs:
|
|
919
|
+
self._mset(first, k, kwargs[k])
|