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.
Files changed (151) hide show
  1. package/.agignore +1 -1
  2. package/.github/workflows/ci.yml +38 -38
  3. package/=template.pyj +5 -5
  4. package/CHANGELOG.md +19 -0
  5. package/HACKING.md +103 -103
  6. package/LICENSE +24 -24
  7. package/PYTHON_GAPS.md +420 -0
  8. package/README.md +153 -29
  9. package/TODO.md +16 -118
  10. package/add-toc-to-readme +2 -2
  11. package/bin/export +75 -75
  12. package/bin/rapydscript +70 -70
  13. package/bin/web-repl-export +102 -102
  14. package/build +2 -2
  15. package/language-service/index.js +237 -8
  16. package/memory/project_string_impl.md +43 -0
  17. package/package.json +1 -1
  18. package/publish.py +37 -37
  19. package/release/baselib-plain-pretty.js +248 -38
  20. package/release/baselib-plain-ugly.js +8 -8
  21. package/release/compiler.js +778 -277
  22. package/release/signatures.json +30 -30
  23. package/session.vim +4 -4
  24. package/setup.cfg +2 -2
  25. package/src/ast.pyj +4 -1
  26. package/src/baselib-builtins.pyj +56 -2
  27. package/src/baselib-containers.pyj +2 -0
  28. package/src/baselib-errors.pyj +7 -3
  29. package/src/baselib-internal.pyj +51 -6
  30. package/src/baselib-str.pyj +5 -3
  31. package/src/compiler.pyj +36 -36
  32. package/src/errors.pyj +30 -30
  33. package/src/lib/aes.pyj +646 -646
  34. package/src/lib/asyncio.pyj +534 -0
  35. package/src/lib/base64.pyj +399 -0
  36. package/src/lib/bisect.pyj +73 -0
  37. package/src/lib/collections.pyj +1 -1
  38. package/src/lib/copy.pyj +120 -120
  39. package/src/lib/csv.pyj +494 -0
  40. package/src/lib/elementmaker.pyj +83 -83
  41. package/src/lib/encodings.pyj +126 -126
  42. package/src/lib/gettext.pyj +569 -569
  43. package/src/lib/heapq.pyj +98 -0
  44. package/src/lib/html.pyj +382 -0
  45. package/src/lib/http/__init__.pyj +98 -0
  46. package/src/lib/http/client.pyj +304 -0
  47. package/src/lib/http/cookies.pyj +236 -0
  48. package/src/lib/itertools.pyj +580 -580
  49. package/src/lib/logging.pyj +672 -0
  50. package/src/lib/math.pyj +193 -193
  51. package/src/lib/operator.pyj +11 -11
  52. package/src/lib/pythonize.pyj +20 -20
  53. package/src/lib/random.pyj +118 -118
  54. package/src/lib/react.pyj +74 -74
  55. package/src/lib/string.pyj +357 -0
  56. package/src/lib/textwrap.pyj +329 -0
  57. package/src/lib/traceback.pyj +63 -63
  58. package/src/lib/urllib/__init__.pyj +14 -0
  59. package/src/lib/urllib/error.pyj +66 -0
  60. package/src/lib/urllib/parse.pyj +475 -0
  61. package/src/lib/urllib/request.pyj +86 -0
  62. package/src/lib/uuid.pyj +77 -77
  63. package/src/monaco-language-service/analyzer.js +5 -2
  64. package/src/monaco-language-service/completions.js +26 -0
  65. package/src/monaco-language-service/diagnostics.js +202 -3
  66. package/src/monaco-language-service/dts.js +550 -550
  67. package/src/monaco-language-service/scope.js +1 -0
  68. package/src/output/comments.pyj +45 -45
  69. package/src/output/exceptions.pyj +201 -201
  70. package/src/output/functions.pyj +152 -6
  71. package/src/output/jsx.pyj +164 -164
  72. package/src/output/loops.pyj +17 -2
  73. package/src/output/modules.pyj +1 -1
  74. package/src/output/operators.pyj +15 -0
  75. package/src/output/stream.pyj +0 -1
  76. package/src/output/treeshake.pyj +182 -182
  77. package/src/output/utils.pyj +72 -72
  78. package/src/parse.pyj +80 -17
  79. package/src/string_interpolation.pyj +72 -72
  80. package/src/tokenizer.pyj +1 -1
  81. package/src/unicode_aliases.pyj +576 -576
  82. package/src/utils.pyj +192 -192
  83. package/test/_import_one.pyj +37 -37
  84. package/test/_import_two/__init__.pyj +11 -11
  85. package/test/_import_two/level2/deep.pyj +4 -4
  86. package/test/_import_two/other.pyj +6 -6
  87. package/test/_import_two/sub.pyj +13 -13
  88. package/test/aes_vectors.pyj +421 -421
  89. package/test/annotations.pyj +80 -80
  90. package/test/async_generators.pyj +144 -0
  91. package/test/asyncio.pyj +307 -0
  92. package/test/base64.pyj +202 -0
  93. package/test/bisect.pyj +178 -0
  94. package/test/csv.pyj +405 -0
  95. package/test/decorators.pyj +77 -77
  96. package/test/docstrings.pyj +39 -39
  97. package/test/elementmaker_test.pyj +45 -45
  98. package/test/float_special.pyj +64 -0
  99. package/test/functions.pyj +151 -151
  100. package/test/generators.pyj +41 -41
  101. package/test/generic.pyj +370 -370
  102. package/test/heapq.pyj +174 -0
  103. package/test/html.pyj +212 -0
  104. package/test/http.pyj +259 -0
  105. package/test/imports.pyj +79 -72
  106. package/test/internationalization.pyj +73 -73
  107. package/test/lint.pyj +164 -164
  108. package/test/logging.pyj +356 -0
  109. package/test/long.pyj +130 -0
  110. package/test/loops.pyj +85 -85
  111. package/test/numpy.pyj +734 -734
  112. package/test/parenthesized_with.pyj +141 -0
  113. package/test/python_compat.pyj +3 -5
  114. package/test/python_modulo.pyj +76 -0
  115. package/test/python_modulo_off.pyj +21 -0
  116. package/test/repl.pyj +121 -121
  117. package/test/scoped_flags.pyj +76 -76
  118. package/test/str.pyj +14 -0
  119. package/test/string.pyj +245 -0
  120. package/test/textwrap.pyj +172 -0
  121. package/test/type_display.pyj +48 -0
  122. package/test/type_enforcement.pyj +164 -0
  123. package/test/unit/index.js +14 -6
  124. package/test/unit/language-service-completions.js +119 -0
  125. package/test/unit/language-service-dts.js +543 -543
  126. package/test/unit/language-service-hover.js +455 -455
  127. package/test/unit/language-service-scope.js +32 -0
  128. package/test/unit/language-service.js +127 -3
  129. package/test/unit/run-language-service.js +17 -3
  130. package/test/unit/web-repl.js +2094 -29
  131. package/test/urllib.pyj +193 -0
  132. package/tools/compile.js +1 -1
  133. package/tools/compiler.d.ts +367 -367
  134. package/tools/completer.js +131 -131
  135. package/tools/embedded_compiler.js +7 -7
  136. package/tools/gettext.js +185 -185
  137. package/tools/ini.js +65 -65
  138. package/tools/msgfmt.js +187 -187
  139. package/tools/repl.js +223 -223
  140. package/tools/test.js +118 -118
  141. package/tools/utils.js +128 -128
  142. package/tools/web_repl.js +95 -95
  143. package/try +41 -41
  144. package/web-repl/env.js +196 -196
  145. package/web-repl/index.html +163 -163
  146. package/web-repl/main.js +1 -1
  147. package/web-repl/prism.css +139 -139
  148. package/web-repl/prism.js +113 -113
  149. package/web-repl/rapydscript.js +224 -224
  150. package/web-repl/sha1.js +25 -25
  151. 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')
@@ -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())
@@ -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')