rapydscript-ns 0.9.2 → 0.9.3
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/.agignore +1 -1
- package/.github/workflows/ci.yml +38 -38
- package/=template.pyj +5 -5
- package/CHANGELOG.md +19 -0
- package/HACKING.md +103 -103
- package/LICENSE +24 -24
- package/PYTHON_GAPS.md +420 -0
- package/README.md +153 -29
- package/TODO.md +16 -118
- package/add-toc-to-readme +2 -2
- package/bin/export +75 -75
- package/bin/rapydscript +70 -70
- package/bin/web-repl-export +102 -102
- package/build +2 -2
- package/language-service/index.js +237 -8
- package/memory/project_string_impl.md +43 -0
- package/package.json +1 -1
- package/publish.py +37 -37
- 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/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/ast.pyj +4 -1
- package/src/baselib-builtins.pyj +56 -2
- package/src/baselib-containers.pyj +2 -0
- package/src/baselib-errors.pyj +7 -3
- package/src/baselib-internal.pyj +51 -6
- package/src/baselib-str.pyj +5 -3
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/aes.pyj +646 -646
- 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 +1 -1
- package/src/lib/copy.pyj +120 -120
- package/src/lib/csv.pyj +494 -0
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- package/src/lib/gettext.pyj +569 -569
- 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/itertools.pyj +580 -580
- package/src/lib/logging.pyj +672 -0
- package/src/lib/math.pyj +193 -193
- package/src/lib/operator.pyj +11 -11
- package/src/lib/pythonize.pyj +20 -20
- package/src/lib/random.pyj +118 -118
- package/src/lib/react.pyj +74 -74
- package/src/lib/string.pyj +357 -0
- package/src/lib/textwrap.pyj +329 -0
- package/src/lib/traceback.pyj +63 -63
- 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/lib/uuid.pyj +77 -77
- 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 +202 -3
- package/src/monaco-language-service/dts.js +550 -550
- package/src/monaco-language-service/scope.js +1 -0
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -201
- package/src/output/functions.pyj +152 -6
- package/src/output/jsx.pyj +164 -164
- 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/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/parse.pyj +80 -17
- package/src/string_interpolation.pyj +72 -72
- package/src/tokenizer.pyj +1 -1
- package/src/unicode_aliases.pyj +576 -576
- package/src/utils.pyj +192 -192
- package/test/_import_one.pyj +37 -37
- package/test/_import_two/__init__.pyj +11 -11
- package/test/_import_two/level2/deep.pyj +4 -4
- package/test/_import_two/other.pyj +6 -6
- package/test/_import_two/sub.pyj +13 -13
- package/test/aes_vectors.pyj +421 -421
- package/test/annotations.pyj +80 -80
- package/test/async_generators.pyj +144 -0
- package/test/asyncio.pyj +307 -0
- package/test/base64.pyj +202 -0
- package/test/bisect.pyj +178 -0
- package/test/csv.pyj +405 -0
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/float_special.pyj +64 -0
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- 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/internationalization.pyj +73 -73
- package/test/lint.pyj +164 -164
- package/test/logging.pyj +356 -0
- package/test/long.pyj +130 -0
- package/test/loops.pyj +85 -85
- package/test/numpy.pyj +734 -734
- package/test/parenthesized_with.pyj +141 -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/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- 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 +14 -6
- package/test/unit/language-service-completions.js +119 -0
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service-scope.js +32 -0
- package/test/unit/language-service.js +127 -3
- package/test/unit/run-language-service.js +17 -3
- package/test/unit/web-repl.js +2094 -29
- package/test/urllib.pyj +193 -0
- package/tools/compile.js +1 -1
- package/tools/compiler.d.ts +367 -367
- package/tools/completer.js +131 -131
- package/tools/embedded_compiler.js +7 -7
- package/tools/gettext.js +185 -185
- package/tools/ini.js +65 -65
- package/tools/msgfmt.js +187 -187
- package/tools/repl.js +223 -223
- package/tools/test.js +118 -118
- package/tools/utils.js +128 -128
- package/tools/web_repl.js +95 -95
- package/try +41 -41
- package/web-repl/env.js +196 -196
- package/web-repl/index.html +163 -163
- package/web-repl/main.js +1 -1
- package/web-repl/prism.css +139 -139
- package/web-repl/prism.js +113 -113
- package/web-repl/rapydscript.js +224 -224
- package/web-repl/sha1.js +25 -25
- package/test/omit_function_metadata.pyj +0 -20
package/test/csv.pyj
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
# globals: assrt
|
|
2
|
+
# vim:fileencoding=utf-8
|
|
3
|
+
#
|
|
4
|
+
# csv.pyj
|
|
5
|
+
# Tests for the csv standard library module.
|
|
6
|
+
|
|
7
|
+
from csv import reader, writer, DictReader, DictWriter
|
|
8
|
+
from csv import Dialect, excel, excel_tab, unix_dialect
|
|
9
|
+
from csv import register_dialect, unregister_dialect, get_dialect, list_dialects
|
|
10
|
+
from csv import field_size_limit, Error
|
|
11
|
+
from csv import QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE
|
|
12
|
+
from io import StringIO
|
|
13
|
+
|
|
14
|
+
ae = assrt.equal
|
|
15
|
+
ade = assrt.deepEqual
|
|
16
|
+
ok = assrt.ok
|
|
17
|
+
|
|
18
|
+
# ── 1. Constants ──────────────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
ae(QUOTE_MINIMAL, 0)
|
|
21
|
+
ae(QUOTE_ALL, 1)
|
|
22
|
+
ae(QUOTE_NONNUMERIC, 2)
|
|
23
|
+
ae(QUOTE_NONE, 3)
|
|
24
|
+
|
|
25
|
+
# ── 2. Basic reader — list input ──────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
_r1 = reader(['a,b,c', '1,2,3'])
|
|
28
|
+
_row = _r1.__next__()
|
|
29
|
+
ade(_row, ['a', 'b', 'c'])
|
|
30
|
+
_row = _r1.__next__()
|
|
31
|
+
ade(_row, ['1', '2', '3'])
|
|
32
|
+
_done = False
|
|
33
|
+
try:
|
|
34
|
+
_r1.__next__()
|
|
35
|
+
except StopIteration:
|
|
36
|
+
_done = True
|
|
37
|
+
ok(_done, 'reader raises StopIteration at end')
|
|
38
|
+
|
|
39
|
+
# ── 3. Reader via for loop ─────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
_rows = []
|
|
42
|
+
for _row in reader(['x,y', 'p,q']):
|
|
43
|
+
_rows.push(_row)
|
|
44
|
+
ae(_rows.length, 2)
|
|
45
|
+
ade(_rows[0], ['x', 'y'])
|
|
46
|
+
ade(_rows[1], ['p', 'q'])
|
|
47
|
+
|
|
48
|
+
# ── 4. Reader — quoted fields ─────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
_rows = []
|
|
51
|
+
for _row in reader(['"hello, world",foo', '"has ""quotes""",bar']):
|
|
52
|
+
_rows.push(_row)
|
|
53
|
+
ade(_rows[0], ['hello, world', 'foo'])
|
|
54
|
+
ade(_rows[1], ['has "quotes"', 'bar'])
|
|
55
|
+
|
|
56
|
+
# ── 5. Reader — custom delimiter ──────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
_rows = []
|
|
59
|
+
for _row in reader(['a|b|c', '1|2|3'], delimiter='|'):
|
|
60
|
+
_rows.push(_row)
|
|
61
|
+
ade(_rows[0], ['a', 'b', 'c'])
|
|
62
|
+
ade(_rows[1], ['1', '2', '3'])
|
|
63
|
+
|
|
64
|
+
# ── 6. Reader — skipinitialspace ──────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
_rows = []
|
|
67
|
+
for _row in reader(['a, b, c'], skipinitialspace=True):
|
|
68
|
+
_rows.push(_row)
|
|
69
|
+
ade(_rows[0], ['a', 'b', 'c'])
|
|
70
|
+
|
|
71
|
+
# ── 7. Reader — tab-delimited (excel-tab dialect) ────────────────────────────
|
|
72
|
+
|
|
73
|
+
_rows = []
|
|
74
|
+
for _row in reader(['a\tb\tc'], dialect='excel-tab'):
|
|
75
|
+
_rows.push(_row)
|
|
76
|
+
ade(_rows[0], ['a', 'b', 'c'])
|
|
77
|
+
|
|
78
|
+
# ── 8. Reader — QUOTE_NONNUMERIC converts unquoted fields to float ────────────
|
|
79
|
+
|
|
80
|
+
_rows = []
|
|
81
|
+
for _row in reader(['"text",3.14,42'], quoting=QUOTE_NONNUMERIC):
|
|
82
|
+
_rows.push(_row)
|
|
83
|
+
ae(_rows[0][0], 'text') # quoted → stays string
|
|
84
|
+
ae(_rows[0][1], 3.14) # unquoted numeric → float
|
|
85
|
+
ae(_rows[0][2], 42.0) # unquoted int → float
|
|
86
|
+
|
|
87
|
+
# ── 9. Reader — multi-line quoted field ───────────────────────────────────────
|
|
88
|
+
|
|
89
|
+
_rows = []
|
|
90
|
+
for _row in reader(['"line1\nline2",b']):
|
|
91
|
+
_rows.push(_row)
|
|
92
|
+
ae(_rows[0][0], 'line1\nline2')
|
|
93
|
+
ae(_rows[0][1], 'b')
|
|
94
|
+
|
|
95
|
+
# ── 10. Reader — empty fields and trailing delimiter ─────────────────────────
|
|
96
|
+
|
|
97
|
+
_rows = []
|
|
98
|
+
for _row in reader(['a,,c', ',,']):
|
|
99
|
+
_rows.push(_row)
|
|
100
|
+
ade(_rows[0], ['a', '', 'c'])
|
|
101
|
+
ade(_rows[1], ['', '', ''])
|
|
102
|
+
|
|
103
|
+
# ── 11. Reader — file-like input (StringIO) ───────────────────────────────────
|
|
104
|
+
|
|
105
|
+
_sio_in = StringIO('hello,world\nfoo,bar\n')
|
|
106
|
+
_rows = []
|
|
107
|
+
for _row in reader(_sio_in):
|
|
108
|
+
_rows.push(_row)
|
|
109
|
+
ae(_rows.length, 2)
|
|
110
|
+
ade(_rows[0], ['hello', 'world'])
|
|
111
|
+
ade(_rows[1], ['foo', 'bar'])
|
|
112
|
+
|
|
113
|
+
# ── 12. Reader — line_num ─────────────────────────────────────────────────────
|
|
114
|
+
|
|
115
|
+
_r2 = reader(['a,b', 'c,d', 'e,f'])
|
|
116
|
+
ae(_r2.line_num, 0)
|
|
117
|
+
_r2.__next__()
|
|
118
|
+
ae(_r2.line_num, 1)
|
|
119
|
+
_r2.__next__()
|
|
120
|
+
ae(_r2.line_num, 2)
|
|
121
|
+
|
|
122
|
+
# ── 13. Reader — list items with trailing newlines ───────────────────────────
|
|
123
|
+
|
|
124
|
+
_rows = []
|
|
125
|
+
for _row in reader(['a,b\n', 'c,d\n']):
|
|
126
|
+
_rows.push(_row)
|
|
127
|
+
ae(_rows.length, 2)
|
|
128
|
+
ade(_rows[0], ['a', 'b'])
|
|
129
|
+
ade(_rows[1], ['c', 'd'])
|
|
130
|
+
|
|
131
|
+
# ── 14. Reader — empty list ───────────────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
_rows = []
|
|
134
|
+
for _row in reader([]):
|
|
135
|
+
_rows.push(_row)
|
|
136
|
+
ae(_rows.length, 0)
|
|
137
|
+
|
|
138
|
+
# ── 15. Reader — single empty field ──────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
_rows = []
|
|
141
|
+
for _row in reader(['']):
|
|
142
|
+
_rows.push(_row)
|
|
143
|
+
ae(_rows.length, 1)
|
|
144
|
+
ade(_rows[0], [''])
|
|
145
|
+
|
|
146
|
+
# ── 16. Reader — dialect attribute ────────────────────────────────────────────
|
|
147
|
+
|
|
148
|
+
_r3 = reader(['a,b'])
|
|
149
|
+
ae(_r3.dialect.delimiter, ',')
|
|
150
|
+
ae(_r3.dialect.quotechar, '"')
|
|
151
|
+
ok(_r3.dialect.doublequote)
|
|
152
|
+
|
|
153
|
+
# ── 17. Writer — basic writerow ───────────────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
_out = StringIO()
|
|
156
|
+
_w = writer(_out)
|
|
157
|
+
_w.writerow(['a', 'b', 'c'])
|
|
158
|
+
ae(_out.getvalue(), 'a,b,c\r\n')
|
|
159
|
+
|
|
160
|
+
# ── 18. Writer — writerow with field needing quoting ─────────────────────────
|
|
161
|
+
|
|
162
|
+
_out = StringIO()
|
|
163
|
+
_w = writer(_out)
|
|
164
|
+
_w.writerow(['hello, world', 'foo'])
|
|
165
|
+
ae(_out.getvalue(), '"hello, world",foo\r\n')
|
|
166
|
+
|
|
167
|
+
# ── 19. Writer — writerow quotes double-quote characters ─────────────────────
|
|
168
|
+
|
|
169
|
+
_out = StringIO()
|
|
170
|
+
_w = writer(_out)
|
|
171
|
+
_w.writerow(['say "hi"', 'ok'])
|
|
172
|
+
ae(_out.getvalue(), '"say ""hi""",ok\r\n')
|
|
173
|
+
|
|
174
|
+
# ── 20. Writer — QUOTE_ALL ────────────────────────────────────────────────────
|
|
175
|
+
|
|
176
|
+
_out = StringIO()
|
|
177
|
+
_w = writer(_out, quoting=QUOTE_ALL)
|
|
178
|
+
_w.writerow(['a', 'b', 'c'])
|
|
179
|
+
ae(_out.getvalue(), '"a","b","c"\r\n')
|
|
180
|
+
|
|
181
|
+
# ── 21. Writer — QUOTE_NONE with escapechar ───────────────────────────────────
|
|
182
|
+
|
|
183
|
+
_out = StringIO()
|
|
184
|
+
_w = writer(_out, quoting=QUOTE_NONE, escapechar='\\')
|
|
185
|
+
_w.writerow(['a,b', 'c'])
|
|
186
|
+
ae(_out.getvalue(), 'a\\,b,c\r\n')
|
|
187
|
+
|
|
188
|
+
# ── 22. Writer — custom delimiter ─────────────────────────────────────────────
|
|
189
|
+
|
|
190
|
+
_out = StringIO()
|
|
191
|
+
_w = writer(_out, delimiter='|')
|
|
192
|
+
_w.writerow(['x', 'y', 'z'])
|
|
193
|
+
ae(_out.getvalue(), 'x|y|z\r\n')
|
|
194
|
+
|
|
195
|
+
# ── 23. Writer — writerows ────────────────────────────────────────────────────
|
|
196
|
+
|
|
197
|
+
_out = StringIO()
|
|
198
|
+
_w = writer(_out)
|
|
199
|
+
_w.writerows([['1', '2'], ['3', '4']])
|
|
200
|
+
ae(_out.getvalue(), '1,2\r\n3,4\r\n')
|
|
201
|
+
|
|
202
|
+
# ── 24. Writer — unix dialect (lineterminator=\n) ────────────────────────────
|
|
203
|
+
|
|
204
|
+
_out = StringIO()
|
|
205
|
+
_w = writer(_out, dialect='unix')
|
|
206
|
+
_w.writerow(['a', 'b'])
|
|
207
|
+
ae(_out.getvalue(), '"a","b"\n')
|
|
208
|
+
|
|
209
|
+
# ── 25. Writer — numeric values ───────────────────────────────────────────────
|
|
210
|
+
|
|
211
|
+
_out = StringIO()
|
|
212
|
+
_w = writer(_out)
|
|
213
|
+
_w.writerow([1, 3.14, True])
|
|
214
|
+
ae(_out.getvalue(), '1,3.14,true\r\n')
|
|
215
|
+
|
|
216
|
+
# ── 26. DictReader — fieldnames from first row ───────────────────────────────
|
|
217
|
+
|
|
218
|
+
_dr = DictReader(['name,age', 'Alice,30', 'Bob,25'])
|
|
219
|
+
_rows = []
|
|
220
|
+
for _row in _dr:
|
|
221
|
+
_rows.push(_row)
|
|
222
|
+
ae(_rows.length, 2)
|
|
223
|
+
ae(_rows[0]['name'], 'Alice')
|
|
224
|
+
ae(_rows[0]['age'], '30')
|
|
225
|
+
ae(_rows[1]['name'], 'Bob')
|
|
226
|
+
ae(_rows[1]['age'], '25')
|
|
227
|
+
|
|
228
|
+
# ── 27. DictReader — provided fieldnames ─────────────────────────────────────
|
|
229
|
+
|
|
230
|
+
_dr2 = DictReader(['Alice,30', 'Bob,25'], fieldnames=['name', 'age'])
|
|
231
|
+
_rows = []
|
|
232
|
+
for _row in _dr2:
|
|
233
|
+
_rows.push(_row)
|
|
234
|
+
ae(_rows.length, 2)
|
|
235
|
+
ae(_rows[0]['name'], 'Alice')
|
|
236
|
+
ae(_rows[0]['age'], '30')
|
|
237
|
+
|
|
238
|
+
# ── 28. DictReader — restval for missing fields ───────────────────────────────
|
|
239
|
+
|
|
240
|
+
_dr3 = DictReader(['name,age,city', 'Alice,30'], restval='N/A')
|
|
241
|
+
_rows = []
|
|
242
|
+
for _row in _dr3:
|
|
243
|
+
_rows.push(_row)
|
|
244
|
+
ae(_rows[0]['city'], 'N/A')
|
|
245
|
+
|
|
246
|
+
# ── 29. DictReader — extra fields go to restkey ──────────────────────────────
|
|
247
|
+
|
|
248
|
+
_dr4 = DictReader(['name,age', 'Alice,30,extra1,extra2'])
|
|
249
|
+
_row = _dr4.__next__()
|
|
250
|
+
ok(_row['EXTRA'] is not None)
|
|
251
|
+
ae(_row['EXTRA'].length, 2)
|
|
252
|
+
ae(_row['EXTRA'][0], 'extra1')
|
|
253
|
+
|
|
254
|
+
# ── 30. DictReader — empty input ─────────────────────────────────────────────
|
|
255
|
+
|
|
256
|
+
_dr5 = DictReader([])
|
|
257
|
+
_empty = True
|
|
258
|
+
for _row in _dr5:
|
|
259
|
+
_empty = False
|
|
260
|
+
ok(_empty, 'DictReader on empty input produces no rows')
|
|
261
|
+
|
|
262
|
+
# ── 31. DictWriter — basic writerow ──────────────────────────────────────────
|
|
263
|
+
|
|
264
|
+
_out = StringIO()
|
|
265
|
+
_dw = DictWriter(_out, ['name', 'age'])
|
|
266
|
+
_dw.writerow({'name': 'Alice', 'age': '30'})
|
|
267
|
+
ae(_out.getvalue(), 'Alice,30\r\n')
|
|
268
|
+
|
|
269
|
+
# ── 32. DictWriter — writeheader ──────────────────────────────────────────────
|
|
270
|
+
|
|
271
|
+
_out = StringIO()
|
|
272
|
+
_dw = DictWriter(_out, ['name', 'age'])
|
|
273
|
+
_dw.writeheader()
|
|
274
|
+
ae(_out.getvalue(), 'name,age\r\n')
|
|
275
|
+
|
|
276
|
+
# ── 33. DictWriter — restval for missing fields ───────────────────────────────
|
|
277
|
+
|
|
278
|
+
_out = StringIO()
|
|
279
|
+
_dw = DictWriter(_out, ['name', 'age', 'city'], restval='')
|
|
280
|
+
_dw.writerow({'name': 'Alice', 'age': '30'})
|
|
281
|
+
ae(_out.getvalue(), 'Alice,30,\r\n')
|
|
282
|
+
|
|
283
|
+
# ── 34. DictWriter — writerows ────────────────────────────────────────────────
|
|
284
|
+
|
|
285
|
+
_out = StringIO()
|
|
286
|
+
_dw = DictWriter(_out, ['x', 'y'])
|
|
287
|
+
_dw.writerows([{'x': '1', 'y': '2'}, {'x': '3', 'y': '4'}])
|
|
288
|
+
ae(_out.getvalue(), '1,2\r\n3,4\r\n')
|
|
289
|
+
|
|
290
|
+
# ── 35. DictWriter — extrasaction='raise' detects unknown fields ──────────────
|
|
291
|
+
|
|
292
|
+
_out = StringIO()
|
|
293
|
+
_dw2 = DictWriter(_out, ['name'], extrasaction='raise')
|
|
294
|
+
_extra_raised = False
|
|
295
|
+
try:
|
|
296
|
+
_dw2.writerow({'name': 'Alice', 'foo': 'bar'})
|
|
297
|
+
except ValueError:
|
|
298
|
+
_extra_raised = True
|
|
299
|
+
ok(_extra_raised, "DictWriter extrasaction='raise' should raise ValueError for extra fields")
|
|
300
|
+
|
|
301
|
+
# ── 36. DictWriter — extrasaction='ignore' silently ignores extra fields ──────
|
|
302
|
+
|
|
303
|
+
_out = StringIO()
|
|
304
|
+
_dw3 = DictWriter(_out, ['name'], extrasaction='ignore')
|
|
305
|
+
_dw3.writerow({'name': 'Alice', 'extra': 'ignored'})
|
|
306
|
+
ae(_out.getvalue(), 'Alice\r\n')
|
|
307
|
+
|
|
308
|
+
# ── 37. register_dialect / list_dialects / get_dialect ───────────────────────
|
|
309
|
+
|
|
310
|
+
register_dialect('pipes', delimiter='|')
|
|
311
|
+
_dl = list_dialects()
|
|
312
|
+
ok(_dl.indexOf('pipes') >= 0, 'pipes dialect should be in list_dialects()')
|
|
313
|
+
|
|
314
|
+
_d = get_dialect('pipes')
|
|
315
|
+
ae(_d.delimiter, '|')
|
|
316
|
+
|
|
317
|
+
_out = StringIO()
|
|
318
|
+
_w = writer(_out, dialect='pipes')
|
|
319
|
+
_w.writerow(['a', 'b'])
|
|
320
|
+
ae(_out.getvalue(), 'a|b\r\n')
|
|
321
|
+
|
|
322
|
+
# ── 38. unregister_dialect ────────────────────────────────────────────────────
|
|
323
|
+
|
|
324
|
+
unregister_dialect('pipes')
|
|
325
|
+
_dl2 = list_dialects()
|
|
326
|
+
ok(_dl2.indexOf('pipes') < 0, 'pipes dialect removed after unregister_dialect')
|
|
327
|
+
|
|
328
|
+
_err_raised = False
|
|
329
|
+
try:
|
|
330
|
+
get_dialect('pipes')
|
|
331
|
+
except Error:
|
|
332
|
+
_err_raised = True
|
|
333
|
+
ok(_err_raised, 'get_dialect on unknown name should raise csv.Error')
|
|
334
|
+
|
|
335
|
+
# ── 39. unregister_dialect on built-ins raises Error ─────────────────────────
|
|
336
|
+
|
|
337
|
+
_unregister_bad = False
|
|
338
|
+
try:
|
|
339
|
+
unregister_dialect('no_such_dialect')
|
|
340
|
+
except Error:
|
|
341
|
+
_unregister_bad = True
|
|
342
|
+
ok(_unregister_bad, 'unregister_dialect on unknown name should raise csv.Error')
|
|
343
|
+
|
|
344
|
+
# ── 40. reader with unknown dialect raises Error ──────────────────────────────
|
|
345
|
+
|
|
346
|
+
_bad_dialect = False
|
|
347
|
+
try:
|
|
348
|
+
reader(['a,b'], dialect='nonexistent')
|
|
349
|
+
except Error:
|
|
350
|
+
_bad_dialect = True
|
|
351
|
+
ok(_bad_dialect, 'reader with unknown dialect should raise csv.Error')
|
|
352
|
+
|
|
353
|
+
# ── 41. field_size_limit ──────────────────────────────────────────────────────
|
|
354
|
+
|
|
355
|
+
ae(field_size_limit(), 131072)
|
|
356
|
+
_old = field_size_limit(65536)
|
|
357
|
+
ae(_old, 131072)
|
|
358
|
+
ae(field_size_limit(), 65536)
|
|
359
|
+
field_size_limit(131072) # restore
|
|
360
|
+
|
|
361
|
+
# ── 42. list_dialects includes defaults ───────────────────────────────────────
|
|
362
|
+
|
|
363
|
+
_default_dialects = list_dialects()
|
|
364
|
+
ok(_default_dialects.indexOf('excel') >= 0)
|
|
365
|
+
ok(_default_dialects.indexOf('excel-tab') >= 0)
|
|
366
|
+
ok(_default_dialects.indexOf('unix') >= 0)
|
|
367
|
+
|
|
368
|
+
# ── 43. Writer — dialect attribute ────────────────────────────────────────────
|
|
369
|
+
|
|
370
|
+
_out = StringIO()
|
|
371
|
+
_w4 = writer(_out, dialect='excel-tab')
|
|
372
|
+
ae(_w4.dialect.delimiter, '\t')
|
|
373
|
+
|
|
374
|
+
# ── 44. Round-trip: write then read ──────────────────────────────────────────
|
|
375
|
+
|
|
376
|
+
_buf = StringIO()
|
|
377
|
+
_wrt = writer(_buf)
|
|
378
|
+
_wrt.writerow(['name', 'age', 'city'])
|
|
379
|
+
_wrt.writerow(['Alice', '30', 'New York'])
|
|
380
|
+
_wrt.writerow(['Bob\'s Diner', '25', 'Los Angeles, CA'])
|
|
381
|
+
_buf.seek(0)
|
|
382
|
+
_result = []
|
|
383
|
+
for _r in reader(_buf):
|
|
384
|
+
_result.push(_r)
|
|
385
|
+
ae(_result.length, 3)
|
|
386
|
+
ade(_result[0], ['name', 'age', 'city'])
|
|
387
|
+
ade(_result[1], ['Alice', '30', 'New York'])
|
|
388
|
+
ade(_result[2], ["Bob's Diner", '25', 'Los Angeles, CA'])
|
|
389
|
+
|
|
390
|
+
# ── 45. Round-trip: DictWriter then DictReader ───────────────────────────────
|
|
391
|
+
|
|
392
|
+
_buf2 = StringIO()
|
|
393
|
+
_dw4 = DictWriter(_buf2, ['name', 'score'])
|
|
394
|
+
_dw4.writeheader()
|
|
395
|
+
_dw4.writerow({'name': 'Eve', 'score': '99'})
|
|
396
|
+
_dw4.writerow({'name': 'Frank', 'score': '88'})
|
|
397
|
+
_buf2.seek(0)
|
|
398
|
+
_result2 = []
|
|
399
|
+
for _r in DictReader(_buf2):
|
|
400
|
+
_result2.push(_r)
|
|
401
|
+
ae(_result2.length, 2)
|
|
402
|
+
ae(_result2[0]['name'], 'Eve')
|
|
403
|
+
ae(_result2[0]['score'], '99')
|
|
404
|
+
ae(_result2[1]['name'], 'Frank')
|
|
405
|
+
ae(_result2[1]['score'], '88')
|
package/test/decorators.pyj
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
# vim:fileencoding=utf-8
|
|
2
|
-
# License: BSD Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
|
|
4
|
-
def double(f):
|
|
5
|
-
return def (x):
|
|
6
|
-
return 2 * f(x)
|
|
7
|
-
|
|
8
|
-
def triple(f):
|
|
9
|
-
return def(x):
|
|
10
|
-
return 3 * f(x)
|
|
11
|
-
|
|
12
|
-
@double
|
|
13
|
-
def half(x):
|
|
14
|
-
return x // 2
|
|
15
|
-
|
|
16
|
-
@double
|
|
17
|
-
def f1(x):
|
|
18
|
-
return x
|
|
19
|
-
|
|
20
|
-
@double
|
|
21
|
-
@triple
|
|
22
|
-
def f2(x):
|
|
23
|
-
return x
|
|
24
|
-
|
|
25
|
-
def append_one(f):
|
|
26
|
-
return def(x):
|
|
27
|
-
ans = f(x)
|
|
28
|
-
ans.push(1)
|
|
29
|
-
return ans
|
|
30
|
-
|
|
31
|
-
def append_two(f):
|
|
32
|
-
return def(x):
|
|
33
|
-
ans = f(x)
|
|
34
|
-
ans.push(2)
|
|
35
|
-
return ans
|
|
36
|
-
|
|
37
|
-
@append_two
|
|
38
|
-
@append_one
|
|
39
|
-
def f3():
|
|
40
|
-
return []
|
|
41
|
-
|
|
42
|
-
o = {'double':double}
|
|
43
|
-
|
|
44
|
-
@o.double
|
|
45
|
-
def f4():
|
|
46
|
-
return 1
|
|
47
|
-
|
|
48
|
-
assrt.equal(2, half(2))
|
|
49
|
-
assrt.equal(4, f1(2))
|
|
50
|
-
assrt.equal(12, f2(2))
|
|
51
|
-
assrt.equal(2, f4())
|
|
52
|
-
assrt.deepEqual([1, 2], f3())
|
|
53
|
-
|
|
54
|
-
def multiply(amt):
|
|
55
|
-
|
|
56
|
-
def wrapper(f):
|
|
57
|
-
return def ():
|
|
58
|
-
return amt * f()
|
|
59
|
-
|
|
60
|
-
return wrapper
|
|
61
|
-
|
|
62
|
-
@multiply(2)
|
|
63
|
-
def two():
|
|
64
|
-
return 1
|
|
65
|
-
|
|
66
|
-
@multiply(3)
|
|
67
|
-
def three():
|
|
68
|
-
return 1
|
|
69
|
-
|
|
70
|
-
@multiply(2)
|
|
71
|
-
@multiply(2)
|
|
72
|
-
def four():
|
|
73
|
-
return 1
|
|
74
|
-
|
|
75
|
-
assrt.equal(2, two())
|
|
76
|
-
assrt.equal(3, three())
|
|
77
|
-
assrt.equal(4, four())
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
+
|
|
4
|
+
def double(f):
|
|
5
|
+
return def (x):
|
|
6
|
+
return 2 * f(x)
|
|
7
|
+
|
|
8
|
+
def triple(f):
|
|
9
|
+
return def(x):
|
|
10
|
+
return 3 * f(x)
|
|
11
|
+
|
|
12
|
+
@double
|
|
13
|
+
def half(x):
|
|
14
|
+
return x // 2
|
|
15
|
+
|
|
16
|
+
@double
|
|
17
|
+
def f1(x):
|
|
18
|
+
return x
|
|
19
|
+
|
|
20
|
+
@double
|
|
21
|
+
@triple
|
|
22
|
+
def f2(x):
|
|
23
|
+
return x
|
|
24
|
+
|
|
25
|
+
def append_one(f):
|
|
26
|
+
return def(x):
|
|
27
|
+
ans = f(x)
|
|
28
|
+
ans.push(1)
|
|
29
|
+
return ans
|
|
30
|
+
|
|
31
|
+
def append_two(f):
|
|
32
|
+
return def(x):
|
|
33
|
+
ans = f(x)
|
|
34
|
+
ans.push(2)
|
|
35
|
+
return ans
|
|
36
|
+
|
|
37
|
+
@append_two
|
|
38
|
+
@append_one
|
|
39
|
+
def f3():
|
|
40
|
+
return []
|
|
41
|
+
|
|
42
|
+
o = {'double':double}
|
|
43
|
+
|
|
44
|
+
@o.double
|
|
45
|
+
def f4():
|
|
46
|
+
return 1
|
|
47
|
+
|
|
48
|
+
assrt.equal(2, half(2))
|
|
49
|
+
assrt.equal(4, f1(2))
|
|
50
|
+
assrt.equal(12, f2(2))
|
|
51
|
+
assrt.equal(2, f4())
|
|
52
|
+
assrt.deepEqual([1, 2], f3())
|
|
53
|
+
|
|
54
|
+
def multiply(amt):
|
|
55
|
+
|
|
56
|
+
def wrapper(f):
|
|
57
|
+
return def ():
|
|
58
|
+
return amt * f()
|
|
59
|
+
|
|
60
|
+
return wrapper
|
|
61
|
+
|
|
62
|
+
@multiply(2)
|
|
63
|
+
def two():
|
|
64
|
+
return 1
|
|
65
|
+
|
|
66
|
+
@multiply(3)
|
|
67
|
+
def three():
|
|
68
|
+
return 1
|
|
69
|
+
|
|
70
|
+
@multiply(2)
|
|
71
|
+
@multiply(2)
|
|
72
|
+
def four():
|
|
73
|
+
return 1
|
|
74
|
+
|
|
75
|
+
assrt.equal(2, two())
|
|
76
|
+
assrt.equal(3, three())
|
|
77
|
+
assrt.equal(4, four())
|
package/test/docstrings.pyj
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
# vim:fileencoding=utf-8
|
|
2
|
-
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
# globals: ρσ_module_doc__
|
|
4
|
-
|
|
5
|
-
import _import_one
|
|
6
|
-
|
|
7
|
-
def f():
|
|
8
|
-
" A basic docstring "
|
|
9
|
-
pass
|
|
10
|
-
|
|
11
|
-
assrt.equal(f.__doc__, 'A basic docstring')
|
|
12
|
-
assrt.equal(_import_one.__doc__, 'Module level ds1\n\nModule level ds2\nline2\n\nModule level ds 3')
|
|
13
|
-
|
|
14
|
-
def g():
|
|
15
|
-
'''
|
|
16
|
-
A more complex docstring:
|
|
17
|
-
xxx
|
|
18
|
-
yyyy
|
|
19
|
-
|
|
20
|
-
the end
|
|
21
|
-
'''
|
|
22
|
-
pass
|
|
23
|
-
|
|
24
|
-
assrt.equal(g.__doc__, 'A more complex docstring:\n xxx\n yyyy\n\nthe end')
|
|
25
|
-
|
|
26
|
-
class D:
|
|
27
|
-
' Docstring for a class '
|
|
28
|
-
|
|
29
|
-
def method(self):
|
|
30
|
-
'ds for a method'
|
|
31
|
-
pass
|
|
32
|
-
|
|
33
|
-
assrt.equal(D().__doc__, 'Docstring for a class')
|
|
34
|
-
assrt.equal(D().method.__doc__, 'ds for a method')
|
|
35
|
-
|
|
36
|
-
x = def():
|
|
37
|
-
'xxx'
|
|
38
|
-
|
|
39
|
-
assrt.equal(x.__doc__, 'xxx')
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
+
# globals: ρσ_module_doc__
|
|
4
|
+
|
|
5
|
+
import _import_one
|
|
6
|
+
|
|
7
|
+
def f():
|
|
8
|
+
" A basic docstring "
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
assrt.equal(f.__doc__, 'A basic docstring')
|
|
12
|
+
assrt.equal(_import_one.__doc__, 'Module level ds1\n\nModule level ds2\nline2\n\nModule level ds 3')
|
|
13
|
+
|
|
14
|
+
def g():
|
|
15
|
+
'''
|
|
16
|
+
A more complex docstring:
|
|
17
|
+
xxx
|
|
18
|
+
yyyy
|
|
19
|
+
|
|
20
|
+
the end
|
|
21
|
+
'''
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
assrt.equal(g.__doc__, 'A more complex docstring:\n xxx\n yyyy\n\nthe end')
|
|
25
|
+
|
|
26
|
+
class D:
|
|
27
|
+
' Docstring for a class '
|
|
28
|
+
|
|
29
|
+
def method(self):
|
|
30
|
+
'ds for a method'
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
assrt.equal(D().__doc__, 'Docstring for a class')
|
|
34
|
+
assrt.equal(D().method.__doc__, 'ds for a method')
|
|
35
|
+
|
|
36
|
+
x = def():
|
|
37
|
+
'xxx'
|
|
38
|
+
|
|
39
|
+
assrt.equal(x.__doc__, 'xxx')
|