Skip to content

Commit 766f7d9

Browse files
authored
Merge pull request #894 from TranscryptOrg/dev_3.9.4
Merge v3.9.4 updates to master Changelog: Fixed list and string slice so that they properly handle negative step values (Issue 704) Updated slice value assignments to be more consistent with CPython Added str.splitlines() method (Issue 733) Fixed issue with dict.pop not removing None values (Issue 827) Corrected issue with dict.popitem so that it now removes from the tail of the dict like CPython instead of the head Added dict.copy method (Issue 716) Added dict.fromkeys method (Issue 779) Added list.copy method Added validations for list.pop method (Issue 854) Fixed tzname lookup bug in datetime.astimezone Added index range validation for list and string indices when operator overloading is enabled (Issue 637) Added optional default arg to next() function (Issue 831) Updated enumerate function to work properly with generators and is now lazy (Issue 618) Fixed issue with seed for random module not restarting properly (Issue 770) Added more autotests
2 parents 88af746 + 0d3f7cf commit 766f7d9

File tree

15 files changed

+533
-136
lines changed

15 files changed

+533
-136
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def read (*paths):
1010

1111
setup (
1212
name = 'Transcrypt',
13-
version = '3.9.3',
13+
version = '3.9.4',
1414
description = 'Python to JavaScript transpiler, supporting multiple inheritance and generating lean, highly readable code',
1515
long_description = (
1616
read ('README.rst')

transcrypt/development/automated_tests/transcrypt/dictionaries/__init__.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,64 @@ def run (autoTester):
7979

8080
tel = {'guido': 123}
8181
tel.update({'edsger': 42})
82+
autoTester.check (tel)
8283
autoTester.check (tel.setdefault ('linus', 456))
8384
autoTester.check (tel ['linus'])
8485
autoTester.check (tel.setdefault ('guido', 789))
86+
autoTester.check (tel.setdefault ('dennis', None))
87+
autoTester.check (tel.setdefault ('brian'))
88+
autoTester.check (tel)
8589
autoTester.check (tel.pop ('guido', 1))
8690
autoTester.check (tel.pop ('guido', 1))
8791
autoTester.check (tel.pop ('edsger', 2))
8892
autoTester.check (tel.pop ('foo', 'bar'))
8993
autoTester.check (tel.pop ('foo', None))
94+
autoTester.check (tel.get ('baz', 111))
95+
autoTester.check (tel.get ('baz'))
96+
autoTester.check (tel.get ('baz', None))
97+
autoTester.check (tel)
98+
autoTester.check (tel.popitem())
99+
autoTester.check (tel.popitem())
100+
autoTester.check (tel.popitem())
101+
autoTester.check (tel)
102+
autoTester.check ("dictionary is empty",
103+
autoTester.expectException ( lambda: tel.popitem() )
104+
)
105+
106+
d1 = {'c': 2, 'a': 3, 'd': 4, 'b': 1}
107+
autoTester.check(d1)
108+
d2 = d1.copy()
109+
autoTester.check(d2)
110+
d1['a'] = 5
111+
d2['c'] = 6
112+
autoTester.check(d1)
113+
autoTester.check(d2)
114+
d1['d'] = [3, 1, 2]
115+
autoTester.check(d1)
116+
d3 = d1.copy()
117+
autoTester.check(d3)
118+
d3['d'][1] = 9
119+
autoTester.check(d1)
120+
autoTester.check(d3)
121+
d4 = {}
122+
d5 = d4.copy()
123+
autoTester.check(d5)
124+
125+
autoTester.check(dict.fromkeys(['b', 'c', 'a']))
126+
autoTester.check(dict.fromkeys(['b', 'c', 'a'], '42'))
127+
autoTester.check(dict.fromkeys('bca'))
128+
autoTester.check(d1.fromkeys('bca'))
129+
autoTester.check(d1.fromkeys(['b', 'c', 'a']))
130+
autoTester.check(d1.fromkeys(['b', 'c', 'a'], '42'))
131+
autoTester.check({}.fromkeys(['b', 'c', 'a']))
132+
133+
autoTester.check ("not iterable", autoTester.expectException ( lambda: dict.fromkeys(42) ))
134+
autoTester.check ("missing argument", autoTester.expectException ( lambda: dict.fromkeys() ))
135+
136+
# Check pop of None value (issue 827)
137+
a = {'hello': None}
138+
value = a.pop('hello', '<DEFAULT>')
139+
autoTester.check('value = ', value, '; a = ', a)
90140

91141
# Check compound keys (issue 281)
92142
d = {}
@@ -98,6 +148,7 @@ def run (autoTester):
98148
d = {}
99149
d ['a'] = 3777
100150
d [(1, 2)] = 4777
151+
# autoTester.check (d) # Test fails - JS only supports string keys
101152
autoTester.check (d ['a'], d [(1, 2)])
102153
__pragma__ ('noopov')
103154

transcrypt/development/automated_tests/transcrypt/indices_and_slices/__init__.py

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from org.transcrypt.stubs.browser import __pragma__
2+
from copy import copy
3+
14
def run (autoTester):
25
# Right hand side slices
36
all = range (32)
@@ -21,3 +24,189 @@ def run (autoTester):
2124

2225
aList [ : : 2] = [x + 0.001 for x in range (10) if x % 2]
2326
autoTester.check (aList)
27+
28+
allLists = [[], ['a', 'b', 'c', 'd', 'e', 'f', 'g'], ['a', 'b', 'c', 'd'], 'abcdefg', 'abc']
29+
for aList in allLists:
30+
autoTester.check(aList)
31+
autoTester.check(aList[:])
32+
autoTester.check(aList[None:None])
33+
autoTester.check(aList[::])
34+
autoTester.check(aList[::-1])
35+
autoTester.check(aList[-1:-8:-1])
36+
autoTester.check(aList[::2])
37+
autoTester.check(aList[::-2])
38+
autoTester.check(aList[:4:1])
39+
autoTester.check(aList[:4:-1])
40+
autoTester.check(aList[4:])
41+
autoTester.check(aList[4::])
42+
autoTester.check(aList[4::1])
43+
autoTester.check(aList[4::-1])
44+
autoTester.check(aList[1:4])
45+
autoTester.check(aList[1:4:1])
46+
autoTester.check(aList[1:4:2])
47+
autoTester.check(aList[1:4:-2])
48+
autoTester.check(aList[4:1:-2])
49+
autoTester.check(aList[4:1])
50+
autoTester.check(aList[-1:-4])
51+
autoTester.check(aList[-4:-1])
52+
autoTester.check(aList[-4:-1:2])
53+
autoTester.check(aList[-4:-1:-2])
54+
autoTester.check(aList[9:-9:1])
55+
autoTester.check(aList[-9:9:1])
56+
autoTester.check(aList[9:-9:-1])
57+
autoTester.check(aList[-9:9:-1])
58+
autoTester.check(aList[-9:9:-1])
59+
autoTester.check('zero step slice', autoTester.expectException(lambda: print(aList[::0])))
60+
61+
62+
sample_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
63+
64+
autoTester.check("old:", sample_list)
65+
new1 = sample_list.copy()
66+
autoTester.check("new1:", new1)
67+
new2 = sample_list[:]
68+
autoTester.check("new2:", new2)
69+
new3 = list(sample_list)
70+
autoTester.check("new3:", new3)
71+
# new4 = [*sample_list] # Does not work properly
72+
# autoTester.check("new4:", new4)
73+
new1[1] = 'x'
74+
new2[2] = 'y'
75+
new3[3] = 'z'
76+
autoTester.check("updated:", sample_list, new1, new2, new3)
77+
78+
aList = copy(sample_list)
79+
aList[1:3] = ['x', 'y', 'z']
80+
autoTester.check(aList)
81+
82+
aList = copy(sample_list)
83+
aList[1:1] = ['x', 'y', 'z']
84+
autoTester.check(aList)
85+
86+
aList = copy(sample_list)
87+
aList[:] = ['x', 'y', 'z']
88+
autoTester.check(aList)
89+
90+
aList = copy(sample_list)
91+
aList[1:5] = ['x', 'y', 'z']
92+
autoTester.check(aList)
93+
94+
aList = copy(sample_list)
95+
aList[1:5] = 'xyz'
96+
autoTester.check(aList)
97+
98+
aList = copy(sample_list)
99+
aList[0:5:2] = ['x', 'y', 'z']
100+
autoTester.check(aList)
101+
102+
aList = copy(sample_list)
103+
def aTest1(test_list):
104+
test_list[1:5:2] = ['x', 'y', 'z'] # ValueError: attempt to assign sequence of size 3 to extended slice of size 2
105+
autoTester.check('Invalid slice assignment', autoTester.expectException(lambda: aTest1(aList)))
106+
107+
aList = copy(sample_list)
108+
aList[5:2:-1] = ['x', 'y', 'z']
109+
autoTester.check(aList)
110+
111+
aList = copy(sample_list)
112+
aList[5:0:-2] = ['x', 'y', 'z']
113+
autoTester.check(aList)
114+
115+
aList = copy(sample_list)
116+
aList[1:5] = []
117+
autoTester.check(aList)
118+
119+
aList = copy(sample_list)
120+
aList[1:5:1] = []
121+
autoTester.check(aList)
122+
123+
aList = copy(sample_list)
124+
def aTest3(test_list):
125+
test_list[5:1:-1] = [] # ValueError: attempt to assign sequence of size 0 to extended slice of size 4
126+
autoTester.check('Invalid slice assignment', autoTester.expectException(lambda: aTest3(aList)))
127+
128+
aList = copy(sample_list)
129+
def aTest4(test_list):
130+
test_list[5:1:-1] = ['x', 'y', 'z'] # ValueError: attempt to assign sequence of size 3 to extended slice of size 4
131+
autoTester.check('Invalid slice assignment', autoTester.expectException(lambda: aTest4(aList)))
132+
133+
aList = copy(sample_list)
134+
aList[1:5:-1] = []
135+
autoTester.check(aList)
136+
137+
aList = copy(sample_list)
138+
def aTest2(test_list):
139+
test_list[0:5:-1] = ['x', 'y', 'z'] # ValueError: attempt to assign sequence of size 3 to extended slice of size 0
140+
autoTester.check('Invalid slice assignment', autoTester.expectException(lambda: aTest2(aList)))
141+
142+
aList = copy(sample_list)
143+
aList[0:7:3] = ['x', 'y', 'z']
144+
autoTester.check(aList)
145+
146+
aList = copy(sample_list)
147+
def aTest5(test_list):
148+
test_list[1:7:3] = ['x', 'y', 'z'] # ValueError: attempt to assign sequence of size 3 to extended slice of size 2
149+
autoTester.check('Invalid slice assignment', autoTester.expectException(lambda: aTest5(aList)))
150+
151+
aList = copy(sample_list)
152+
def aTest6(test_list):
153+
test_list[7:0:-3] = ['x', 'y', 'z'] # ValueError: attempt to assign sequence of size 3 to extended slice of size 2
154+
autoTester.check('Invalid slice assignment', autoTester.expectException(lambda: aTest6(aList)))
155+
156+
aList = copy(sample_list)
157+
aList[7:0:-3] = ['x', 'y']
158+
autoTester.check(aList)
159+
160+
aList = copy(sample_list)
161+
def aTest7(test_list):
162+
test_list[7:0:0] = ['x', 'y', 'z'] # ValueError: slice step cannot be zero
163+
autoTester.check('zero step slice', autoTester.expectException(lambda: aTest7(aList)))
164+
165+
aList = ['a', 'b', 'c']
166+
aList.remove('b')
167+
autoTester.check(aList)
168+
aList.remove('a')
169+
autoTester.check(aList)
170+
autoTester.check('not in list', autoTester.expectException(lambda: aList.remove('d')))
171+
autoTester.check(aList)
172+
aList.remove('c')
173+
autoTester.check(aList)
174+
autoTester.check('not in list', autoTester.expectException(lambda: aList.remove('c')))
175+
autoTester.check(aList)
176+
177+
aList = ['a', 'b', 'c', 'd', 'e', 'f']
178+
aList.pop(2)
179+
autoTester.check(aList)
180+
aList.pop(0)
181+
autoTester.check(aList)
182+
aList.pop(-3)
183+
autoTester.check(aList)
184+
aList.pop(-1)
185+
autoTester.check(aList)
186+
autoTester.check('out of range', autoTester.expectException(lambda: aList.pop(-3)))
187+
autoTester.check('out of range', autoTester.expectException(lambda: aList.pop(3)))
188+
aList.pop()
189+
autoTester.check(aList)
190+
aList.pop()
191+
autoTester.check(aList)
192+
autoTester.check('empty list', autoTester.expectException(lambda: aList.pop()))
193+
194+
# Check pop of empty list (issue 854)
195+
autoTester.check('empty list', autoTester.expectException(lambda: aList.pop(-1)))
196+
autoTester.check('empty list', autoTester.expectException(lambda: aList.pop(0)))
197+
autoTester.check('empty list', autoTester.expectException(lambda: aList.pop(1)))
198+
199+
# Check for invalid list index (issue 637)
200+
allLists = [['a', 'b', 'c'], 'abc']
201+
for aList in allLists:
202+
__pragma__('opov')
203+
autoTester.check('valid index', autoTester.expectException(lambda: aList[1]))
204+
autoTester.check(aList[1])
205+
autoTester.check('valid index', autoTester.expectException(lambda: aList[-2]))
206+
autoTester.check(aList[-2])
207+
autoTester.check('invalid index', autoTester.expectException(lambda: aList[3]))
208+
autoTester.check('invalid index', autoTester.expectException(lambda: aList[-4]))
209+
__pragma__('noopov')
210+
autoTester.check(aList[1])
211+
# autoTester.check('invalid index', autoTester.expectException(lambda: aList[-4])) # test differs from CPython without opov
212+

transcrypt/development/automated_tests/transcrypt/iterators_and_generators/__init__.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ def __next__ (self): # Should be auto-wrapped in a next (self) by the compile
2323
def __iter__ (self):
2424
return self
2525

26-
def exhaustableGenerator (i):
27-
for i in range (5):
26+
def exhaustableGenerator (n):
27+
for i in range (n):
2828
yield 2 * i
2929

3030
def run (autoTester):
@@ -63,7 +63,24 @@ def run (autoTester):
6363
autoTester.check ('[4]')
6464
for n in iterable:
6565
autoTester.check (n)
66-
66+
67+
iterables = [['a', 'b', 'c', 'd', 'e'], 'abcde', ('a', 'b', 'c', 'd', 'e')]
68+
for iterable in iterables:
69+
# JS does not have tuples so coerce to list of lists
70+
autoTester.check("enumerate",
71+
[list(item) for item in enumerate(iterable)],
72+
[list(item) for item in enumerate(iterable, 1)],
73+
[list(item) for item in enumerate(iterable, start=2)]
74+
)
75+
76+
# issue #618
77+
for iterable in iterables:
78+
autoTester.check('[5]')
79+
for i, n in enumerate(iterable):
80+
toto = str(i) + '-' + str(n)
81+
autoTester.check(toto)
82+
83+
6784
# BEGIN issue 196: for loop over iter (), runs OK but needs JavaScript 6. This should be clearly in the docs.
6885

6986
a = 0
@@ -136,4 +153,8 @@ def mainCoroutine ():
136153
m = mainCoroutine ()
137154
for i in range (5):
138155
m.send (None)
139-
156+
157+
158+
gen3 = iter(range(2))
159+
autoTester.check('next', next(gen3), next(gen3), next(gen3, 8), next(gen3, 9), next(gen3, None))
160+
autoTester.check('StopIteration', autoTester.expectException(lambda: next(gen3)))

transcrypt/development/automated_tests/transcrypt/module_builtin/__init__.py

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
def canonizeString (aString):
66
if __envir__.executor_name == 'transcrypt':
7-
return aString.replace ('\t', '\\t') .replace ('\n', '\\n')
7+
return aString.replace ('\t', '\\t').replace ('\n', '\\n').replace ('\r', '\\r')
88
else:
99
return aString
1010

@@ -35,14 +35,15 @@ def run (autoTester):
3535
max([[5,6,7,8,9],[1,2,3,4]],default=[1,1,1],key=len),
3636
max ([], default='zzz'),
3737
)
38-
# autoTester.check ('max', autoTester.expectException(lambda: max () ))
39-
# autoTester.check ('max', autoTester.expectException(lambda: max (1,2,3,4, default=5) ))
40-
# autoTester.check ('max', autoTester.expectException(lambda: max (default=5)))
41-
# autoTester.check ('max', autoTester.expectException(lambda: max ([])))
42-
# autoTester.check ('max', autoTester.expectException(lambda: max([5,6,7,8,9],[1,2,3,4],default=[1,1,1],key=len) ))
43-
# autoTester.check ('max', autoTester.expectException(lambda: max ([4, 5, 'xyz', 'XYZ']) ))
38+
autoTester.check ('max', autoTester.expectException(lambda: max () ))
39+
autoTester.check ('max', autoTester.expectException(lambda: max (1,2,3,4, default=5) ))
40+
autoTester.check ('max', autoTester.expectException(lambda: max (default=5)))
41+
autoTester.check ('max', autoTester.expectException(lambda: max ([])))
42+
autoTester.check ('max', autoTester.expectException(lambda: max([5,6,7,8,9],[1,2,3,4],default=[1,1,1],key=len) ))
43+
# autoTester.check ('max', autoTester.expectException(lambda: max ([4, 5, 'xyz', 'XYZ']) )) # exception not currently implemented
4444

4545
autoTester.check ('abs', abs (-1), abs (1), abs (0), abs (-0.1), abs (0.1))
46+
autoTester.check ('pow', pow (2, 2), pow(0, 0), pow(1, 0), pow(2, 1), f"{pow(4, 0.5):g}")
4647

4748
autoTester.check ('ord', ord ('a'), ord ('e´'[0])) # This is the 2 codepoint version
4849
autoTester.check ('chr', chr (97), chr (122), chr (65), chr (90)) # a z A Z
@@ -134,21 +135,30 @@ def run (autoTester):
134135
'<br>'
135136
)
136137

138+
lines_to_split = ['', '\n',
139+
'abc\n',
140+
'abc\ndef',
141+
'abc\rdef',
142+
'abc\r\ndef',
143+
'\nabc',
144+
'\nabc\n',
145+
'abc\ndef\r\nghi\rjkl\n',
146+
'abc\ndef\n\nghi\njkl'
147+
]
148+
autoTester.check ('<br>splitlines')
149+
for line in lines_to_split:
150+
autoTester.check (
151+
canonizeStringList(line.splitlines ()),
152+
canonizeStringList(line.splitlines (True)),
153+
)
154+
137155
autoTester.check("isalpha",
138156
"".isalpha(),
139157
"123".isalpha(),
140158
"abc".isalpha(),
141159
"abc123".isalpha(),
142160
)
143161

144-
enumerate_list = ['a', 'b', 'c', 'd', 'e']
145-
# JS does not have tuples so coerce to list of lists
146-
autoTester.check("enumerate",
147-
[list(item) for item in enumerate(enumerate_list)],
148-
[list(item) for item in enumerate(enumerate_list, 1)],
149-
[list(item) for item in enumerate(enumerate_list, start=2)]
150-
)
151-
152162
replace_test = "abcabcabcabc"
153163
autoTester.check("replace",
154164
replace_test.replace("c", "x"),

0 commit comments

Comments
 (0)