rapydscript-ns 0.9.0 → 0.9.2
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 +10 -0
- package/HACKING.md +103 -103
- package/LICENSE +24 -24
- package/README.md +7 -6
- package/TODO.md +116 -1
- 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 +9 -9
- package/language-service/language-service.d.ts +1 -1
- package/package.json +6 -2
- package/publish.py +37 -37
- package/release/compiler.js +246 -231
- package/release/signatures.json +23 -23
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/aes.pyj +646 -646
- package/src/lib/contextlib.pyj +379 -0
- package/src/lib/copy.pyj +120 -120
- package/src/lib/datetime.pyj +712 -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/io.pyj +500 -0
- package/src/lib/itertools.pyj +580 -580
- package/src/lib/json.pyj +227 -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/traceback.pyj +63 -63
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/diagnostics.js +4 -4
- package/src/monaco-language-service/dts.js +550 -550
- package/src/monaco-language-service/index.js +2 -2
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -201
- package/src/output/jsx.pyj +164 -164
- package/src/output/loops.pyj +9 -0
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- 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/contextlib.pyj +362 -0
- package/test/datetime.pyj +500 -0
- package/test/debugger_stmt.pyj +41 -0
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- package/test/imports.pyj +72 -72
- package/test/internationalization.pyj +73 -73
- package/test/io.pyj +316 -0
- package/test/json.pyj +196 -0
- package/test/lint.pyj +164 -164
- package/test/loops.pyj +85 -85
- package/test/numpy.pyj +734 -734
- package/test/omit_function_metadata.pyj +20 -20
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/unit/index.js +66 -0
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service.js +1 -1
- package/test/unit/web-repl.js +533 -0
- package/tools/compiler.d.ts +367 -0
- package/tools/completer.js +131 -131
- 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/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
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
# globals: assrt
|
|
2
|
+
# vim:fileencoding=utf-8
|
|
3
|
+
#
|
|
4
|
+
# datetime.pyj
|
|
5
|
+
# Tests for the datetime standard library (from datetime import ...).
|
|
6
|
+
|
|
7
|
+
from datetime import date, time, datetime, timedelta, MINYEAR, MAXYEAR
|
|
8
|
+
|
|
9
|
+
ae = assrt.equal
|
|
10
|
+
ade = assrt.deepEqual
|
|
11
|
+
ok = assrt.ok
|
|
12
|
+
throws = assrt.throws
|
|
13
|
+
|
|
14
|
+
# ── 1. Constants ──────────────────────────────────────────────────────────────
|
|
15
|
+
# STATUS: ✓ WORKS
|
|
16
|
+
|
|
17
|
+
ae(MINYEAR, 1)
|
|
18
|
+
ae(MAXYEAR, 9999)
|
|
19
|
+
|
|
20
|
+
# ── 2. timedelta construction and normalisation ────────────────────────────────
|
|
21
|
+
# STATUS: ✓ WORKS
|
|
22
|
+
|
|
23
|
+
# Basic positional args
|
|
24
|
+
_td0 = timedelta(0)
|
|
25
|
+
ae(_td0.days, 0)
|
|
26
|
+
ae(_td0.seconds, 0)
|
|
27
|
+
ae(_td0.microseconds, 0)
|
|
28
|
+
|
|
29
|
+
_td1 = timedelta(1)
|
|
30
|
+
ae(_td1.days, 1)
|
|
31
|
+
ae(_td1.seconds, 0)
|
|
32
|
+
|
|
33
|
+
# Keyword args
|
|
34
|
+
_td_kw = timedelta(days=2, seconds=3661)
|
|
35
|
+
ae(_td_kw.days, 2)
|
|
36
|
+
ae(_td_kw.seconds, 3661)
|
|
37
|
+
|
|
38
|
+
# Normalisation: seconds overflow into days
|
|
39
|
+
_td_norm = timedelta(0, 90061) # 25h 1m 1s
|
|
40
|
+
ae(_td_norm.days, 1)
|
|
41
|
+
ae(_td_norm.seconds, 3661)
|
|
42
|
+
|
|
43
|
+
# Normalisation: milliseconds folded in
|
|
44
|
+
_td_ms = timedelta(0, 0, 0, 1500) # 1500 ms
|
|
45
|
+
ae(_td_ms.seconds, 1)
|
|
46
|
+
ae(_td_ms.microseconds, 500000)
|
|
47
|
+
|
|
48
|
+
# Negative timedelta
|
|
49
|
+
_td_neg = timedelta(-1)
|
|
50
|
+
ae(_td_neg.days, -1)
|
|
51
|
+
ae(_td_neg.seconds, 0)
|
|
52
|
+
|
|
53
|
+
# Negative seconds normalised: days=-1, seconds=86399
|
|
54
|
+
_td_neg_s = timedelta(0, -1)
|
|
55
|
+
ae(_td_neg_s.days, -1)
|
|
56
|
+
ae(_td_neg_s.seconds, 86399)
|
|
57
|
+
|
|
58
|
+
# Float days folded into seconds
|
|
59
|
+
_td_frac = timedelta(0, 0, 0, 0, 0, 0, 0) # all zeros
|
|
60
|
+
ae(_td_frac.days, 0)
|
|
61
|
+
|
|
62
|
+
# ── 3. timedelta.total_seconds() ──────────────────────────────────────────────
|
|
63
|
+
# STATUS: ✓ WORKS
|
|
64
|
+
|
|
65
|
+
ae(timedelta(1).total_seconds(), 86400)
|
|
66
|
+
ae(timedelta(0, 3600).total_seconds(), 3600)
|
|
67
|
+
ae(timedelta(0, 0, 500000).total_seconds(), 0.5)
|
|
68
|
+
ae(timedelta(-1).total_seconds(), -86400)
|
|
69
|
+
|
|
70
|
+
# ── 4. timedelta arithmetic (direct method calls) ─────────────────────────────
|
|
71
|
+
# STATUS: ✓ WORKS
|
|
72
|
+
|
|
73
|
+
_a = timedelta(1)
|
|
74
|
+
_b = timedelta(0, 3600)
|
|
75
|
+
_sum = _a.__add__(_b)
|
|
76
|
+
ae(_sum.days, 1)
|
|
77
|
+
ae(_sum.seconds, 3600)
|
|
78
|
+
|
|
79
|
+
_diff = _a.__sub__(_b)
|
|
80
|
+
ae(_diff.days, 0)
|
|
81
|
+
ae(_diff.seconds, 82800) # 86400 - 3600
|
|
82
|
+
|
|
83
|
+
# __neg__
|
|
84
|
+
_neg = _a.__neg__()
|
|
85
|
+
ae(_neg.days, -1)
|
|
86
|
+
ae(_neg.seconds, 0)
|
|
87
|
+
|
|
88
|
+
# __mul__
|
|
89
|
+
_mul = _a.__mul__(3)
|
|
90
|
+
ae(_mul.days, 3)
|
|
91
|
+
|
|
92
|
+
# ── 5. timedelta comparisons ──────────────────────────────────────────────────
|
|
93
|
+
# STATUS: ✓ WORKS
|
|
94
|
+
|
|
95
|
+
_td_a = timedelta(1)
|
|
96
|
+
_td_b = timedelta(2)
|
|
97
|
+
_td_c = timedelta(1)
|
|
98
|
+
|
|
99
|
+
ok(_td_a.__eq__(_td_c))
|
|
100
|
+
ok(not _td_a.__eq__(_td_b))
|
|
101
|
+
ok(_td_a.__lt__(_td_b))
|
|
102
|
+
ok(not _td_b.__lt__(_td_a))
|
|
103
|
+
ok(_td_a.__le__(_td_c))
|
|
104
|
+
ok(_td_b.__gt__(_td_a))
|
|
105
|
+
ok(_td_b.__ge__(_td_b))
|
|
106
|
+
|
|
107
|
+
# ── 6. timedelta str and repr ─────────────────────────────────────────────────
|
|
108
|
+
# STATUS: ✓ WORKS
|
|
109
|
+
|
|
110
|
+
ae(str(timedelta(0)), '0:00:00')
|
|
111
|
+
ae(str(timedelta(1)), '1 day, 0:00:00')
|
|
112
|
+
ae(str(timedelta(2)), '2 days, 0:00:00')
|
|
113
|
+
ae(str(timedelta(-1)), '-1 day, 0:00:00')
|
|
114
|
+
ae(str(timedelta(-2)), '-2 days, 0:00:00')
|
|
115
|
+
ae(str(timedelta(0, 3661)), '1:01:01')
|
|
116
|
+
ae(str(timedelta(0, 0, 100000)), '0:00:00.100000')
|
|
117
|
+
|
|
118
|
+
ae(repr(timedelta(0)), 'datetime.timedelta(0)')
|
|
119
|
+
ae(repr(timedelta(1)), 'datetime.timedelta(days=1)')
|
|
120
|
+
ae(repr(timedelta(0, 3661)), 'datetime.timedelta(seconds=3661)')
|
|
121
|
+
ae(repr(timedelta(0, 0, 1)), 'datetime.timedelta(microseconds=1)')
|
|
122
|
+
ae(repr(timedelta(1, 3661, 1)), 'datetime.timedelta(days=1, seconds=3661, microseconds=1)')
|
|
123
|
+
|
|
124
|
+
# ── 7. timedelta class attributes ─────────────────────────────────────────────
|
|
125
|
+
# STATUS: ✓ WORKS
|
|
126
|
+
|
|
127
|
+
ok(isinstance(timedelta.min, timedelta))
|
|
128
|
+
ok(isinstance(timedelta.max, timedelta))
|
|
129
|
+
ok(isinstance(timedelta.resolution, timedelta))
|
|
130
|
+
ae(timedelta.min.days, -999999999)
|
|
131
|
+
ae(timedelta.max.days, 999999999)
|
|
132
|
+
ae(timedelta.resolution.microseconds, 1)
|
|
133
|
+
|
|
134
|
+
# ── 8. date construction ──────────────────────────────────────────────────────
|
|
135
|
+
# STATUS: ✓ WORKS
|
|
136
|
+
|
|
137
|
+
_d1 = date(2024, 1, 15)
|
|
138
|
+
ae(_d1.year, 2024)
|
|
139
|
+
ae(_d1.month, 1)
|
|
140
|
+
ae(_d1.day, 15)
|
|
141
|
+
|
|
142
|
+
# Min/max class attributes
|
|
143
|
+
ae(date.min.year, MINYEAR)
|
|
144
|
+
ae(date.min.month, 1)
|
|
145
|
+
ae(date.min.day, 1)
|
|
146
|
+
ae(date.max.year, MAXYEAR)
|
|
147
|
+
ae(date.max.month, 12)
|
|
148
|
+
ae(date.max.day, 31)
|
|
149
|
+
|
|
150
|
+
# ── 9. date.fromisoformat ────────────────────────────────────────────────────
|
|
151
|
+
# STATUS: ✓ WORKS
|
|
152
|
+
|
|
153
|
+
_d_iso = date.fromisoformat('2024-01-15')
|
|
154
|
+
ae(_d_iso.year, 2024)
|
|
155
|
+
ae(_d_iso.month, 1)
|
|
156
|
+
ae(_d_iso.day, 15)
|
|
157
|
+
|
|
158
|
+
# ── 10. date.fromordinal / toordinal round-trip ───────────────────────────────
|
|
159
|
+
# STATUS: ✓ WORKS
|
|
160
|
+
|
|
161
|
+
_d_ref = date(2024, 6, 15)
|
|
162
|
+
ae(date.fromordinal(_d_ref.toordinal()).__eq__(_d_ref), True)
|
|
163
|
+
|
|
164
|
+
ae(date(1, 1, 1).toordinal(), 1)
|
|
165
|
+
ae(date.fromordinal(1).year, 1)
|
|
166
|
+
ae(date.fromordinal(1).month, 1)
|
|
167
|
+
ae(date.fromordinal(1).day, 1)
|
|
168
|
+
|
|
169
|
+
# ── 11. date.weekday / isoweekday ────────────────────────────────────────────
|
|
170
|
+
# STATUS: ✓ WORKS
|
|
171
|
+
|
|
172
|
+
# 2024-01-01 is Monday
|
|
173
|
+
ae(date(2024, 1, 1).weekday(), 0) # Monday
|
|
174
|
+
ae(date(2024, 1, 1).isoweekday(), 1)
|
|
175
|
+
ae(date(2024, 1, 7).weekday(), 6) # Sunday
|
|
176
|
+
ae(date(2024, 1, 7).isoweekday(), 7)
|
|
177
|
+
|
|
178
|
+
# ── 12. date.isoformat / str / repr ──────────────────────────────────────────
|
|
179
|
+
# STATUS: ✓ WORKS
|
|
180
|
+
|
|
181
|
+
ae(str(date(2024, 1, 15)), '2024-01-15')
|
|
182
|
+
ae(date(2024, 1, 15).isoformat(), '2024-01-15')
|
|
183
|
+
ae(repr(date(2024, 1, 15)), 'datetime.date(2024, 1, 15)')
|
|
184
|
+
|
|
185
|
+
# ── 13. date arithmetic (direct method calls) ─────────────────────────────────
|
|
186
|
+
# STATUS: ✓ WORKS
|
|
187
|
+
|
|
188
|
+
_d_base = date(2024, 1, 15)
|
|
189
|
+
_d_plus = _d_base.__add__(timedelta(10))
|
|
190
|
+
ae(_d_plus.year, 2024)
|
|
191
|
+
ae(_d_plus.month, 1)
|
|
192
|
+
ae(_d_plus.day, 25)
|
|
193
|
+
|
|
194
|
+
_d_minus = _d_base.__sub__(timedelta(15))
|
|
195
|
+
ae(_d_minus.year, 2023)
|
|
196
|
+
ae(_d_minus.month, 12)
|
|
197
|
+
ae(_d_minus.day, 31)
|
|
198
|
+
|
|
199
|
+
# date - date → timedelta
|
|
200
|
+
_delta = date(2024, 1, 15).__sub__(date(2024, 1, 1))
|
|
201
|
+
ae(_delta.days, 14)
|
|
202
|
+
|
|
203
|
+
# Month boundary
|
|
204
|
+
_d_end = date(2024, 1, 31).__add__(timedelta(1))
|
|
205
|
+
ae(_d_end.month, 2)
|
|
206
|
+
ae(_d_end.day, 1)
|
|
207
|
+
|
|
208
|
+
# Leap year: 2024 is a leap year
|
|
209
|
+
_d_leap = date(2024, 2, 28).__add__(timedelta(1))
|
|
210
|
+
ae(_d_leap.month, 2)
|
|
211
|
+
ae(_d_leap.day, 29)
|
|
212
|
+
|
|
213
|
+
_d_leap2 = date(2024, 2, 29).__add__(timedelta(1))
|
|
214
|
+
ae(_d_leap2.month, 3)
|
|
215
|
+
ae(_d_leap2.day, 1)
|
|
216
|
+
|
|
217
|
+
# ── 14. date comparisons ──────────────────────────────────────────────────────
|
|
218
|
+
# STATUS: ✓ WORKS
|
|
219
|
+
|
|
220
|
+
_da = date(2024, 1, 1)
|
|
221
|
+
_db = date(2024, 1, 15)
|
|
222
|
+
_dc = date(2024, 1, 1)
|
|
223
|
+
|
|
224
|
+
ok(_da.__eq__(_dc))
|
|
225
|
+
ok(not _da.__eq__(_db))
|
|
226
|
+
ok(_da.__lt__(_db))
|
|
227
|
+
ok(not _db.__lt__(_da))
|
|
228
|
+
ok(_da.__le__(_dc))
|
|
229
|
+
ok(_db.__gt__(_da))
|
|
230
|
+
ok(_da.__ge__(_dc))
|
|
231
|
+
|
|
232
|
+
# ── 15. date.replace ─────────────────────────────────────────────────────────
|
|
233
|
+
# STATUS: ✓ WORKS
|
|
234
|
+
|
|
235
|
+
_d_orig = date(2024, 6, 15)
|
|
236
|
+
_d_rep = _d_orig.replace(year=2025)
|
|
237
|
+
ae(_d_rep.year, 2025)
|
|
238
|
+
ae(_d_rep.month, 6)
|
|
239
|
+
ae(_d_rep.day, 15)
|
|
240
|
+
|
|
241
|
+
_d_rep2 = _d_orig.replace(month=12, day=31)
|
|
242
|
+
ae(_d_rep2.year, 2024)
|
|
243
|
+
ae(_d_rep2.month, 12)
|
|
244
|
+
ae(_d_rep2.day, 31)
|
|
245
|
+
|
|
246
|
+
# ── 16. date.strftime ────────────────────────────────────────────────────────
|
|
247
|
+
# STATUS: ✓ WORKS
|
|
248
|
+
|
|
249
|
+
_ds = date(2024, 1, 5)
|
|
250
|
+
ae(_ds.strftime('%Y-%m-%d'), '2024-01-05')
|
|
251
|
+
ae(_ds.strftime('%d/%m/%Y'), '05/01/2024')
|
|
252
|
+
ae(_ds.strftime('%B %d, %Y'), 'January 05, 2024')
|
|
253
|
+
ae(_ds.strftime('%a %b %d'), 'Fri Jan 05')
|
|
254
|
+
ae(_ds.strftime('%%'), '%')
|
|
255
|
+
ae(_ds.strftime('%j'), '005')
|
|
256
|
+
|
|
257
|
+
# ── 17. time construction ─────────────────────────────────────────────────────
|
|
258
|
+
# STATUS: ✓ WORKS
|
|
259
|
+
|
|
260
|
+
_t0 = time(0)
|
|
261
|
+
ae(_t0.hour, 0)
|
|
262
|
+
ae(_t0.minute, 0)
|
|
263
|
+
ae(_t0.second, 0)
|
|
264
|
+
ae(_t0.microsecond, 0)
|
|
265
|
+
|
|
266
|
+
_t1 = time(14, 30, 5, 123456)
|
|
267
|
+
ae(_t1.hour, 14)
|
|
268
|
+
ae(_t1.minute, 30)
|
|
269
|
+
ae(_t1.second, 5)
|
|
270
|
+
ae(_t1.microsecond, 123456)
|
|
271
|
+
|
|
272
|
+
# Min / max
|
|
273
|
+
ae(time.min.hour, 0)
|
|
274
|
+
ae(time.max.hour, 23)
|
|
275
|
+
ae(time.max.minute, 59)
|
|
276
|
+
ae(time.max.second, 59)
|
|
277
|
+
ae(time.max.microsecond, 999999)
|
|
278
|
+
|
|
279
|
+
# ── 18. time.isoformat / str / repr ──────────────────────────────────────────
|
|
280
|
+
# STATUS: ✓ WORKS
|
|
281
|
+
|
|
282
|
+
ae(str(time(0)), '00:00:00')
|
|
283
|
+
ae(str(time(14, 30, 5)), '14:30:05')
|
|
284
|
+
ae(str(time(14, 30, 5, 123456)), '14:30:05.123456')
|
|
285
|
+
ae(time(9).isoformat(), '09:00:00')
|
|
286
|
+
ae(repr(time(14, 30, 5)), 'datetime.time(14, 30, 5)')
|
|
287
|
+
ae(repr(time(14, 30, 5, 123456)), 'datetime.time(14, 30, 5, 123456)')
|
|
288
|
+
ae(repr(time(14)), 'datetime.time(14)')
|
|
289
|
+
|
|
290
|
+
# ── 19. time comparisons ──────────────────────────────────────────────────────
|
|
291
|
+
# STATUS: ✓ WORKS
|
|
292
|
+
|
|
293
|
+
_ta = time(9, 0)
|
|
294
|
+
_tb = time(17, 30)
|
|
295
|
+
_tc = time(9, 0)
|
|
296
|
+
|
|
297
|
+
ok(_ta.__eq__(_tc))
|
|
298
|
+
ok(not _ta.__eq__(_tb))
|
|
299
|
+
ok(_ta.__lt__(_tb))
|
|
300
|
+
ok(_tb.__gt__(_ta))
|
|
301
|
+
ok(_ta.__le__(_tc))
|
|
302
|
+
ok(_tb.__ge__(_tb))
|
|
303
|
+
|
|
304
|
+
# ── 20. time.replace ─────────────────────────────────────────────────────────
|
|
305
|
+
# STATUS: ✓ WORKS
|
|
306
|
+
|
|
307
|
+
_t_orig = time(9, 30, 0)
|
|
308
|
+
_t_rep = _t_orig.replace(hour=17)
|
|
309
|
+
ae(_t_rep.hour, 17)
|
|
310
|
+
ae(_t_rep.minute, 30)
|
|
311
|
+
ae(_t_rep.second, 0)
|
|
312
|
+
|
|
313
|
+
# ── 21. time.strftime ────────────────────────────────────────────────────────
|
|
314
|
+
# STATUS: ✓ WORKS
|
|
315
|
+
|
|
316
|
+
_ts = time(14, 5, 9)
|
|
317
|
+
ae(_ts.strftime('%H:%M:%S'), '14:05:09')
|
|
318
|
+
ae(_ts.strftime('%I %p'), '02 PM')
|
|
319
|
+
|
|
320
|
+
# ── 22. datetime construction ─────────────────────────────────────────────────
|
|
321
|
+
# STATUS: ✓ WORKS
|
|
322
|
+
|
|
323
|
+
_dt = datetime(2024, 1, 15, 9, 30, 45, 123456)
|
|
324
|
+
ae(_dt.year, 2024)
|
|
325
|
+
ae(_dt.month, 1)
|
|
326
|
+
ae(_dt.day, 15)
|
|
327
|
+
ae(_dt.hour, 9)
|
|
328
|
+
ae(_dt.minute, 30)
|
|
329
|
+
ae(_dt.second, 45)
|
|
330
|
+
ae(_dt.microsecond, 123456)
|
|
331
|
+
|
|
332
|
+
# Defaults for time components
|
|
333
|
+
_dt2 = datetime(2024, 6, 1)
|
|
334
|
+
ae(_dt2.hour, 0)
|
|
335
|
+
ae(_dt2.minute, 0)
|
|
336
|
+
ae(_dt2.second, 0)
|
|
337
|
+
ae(_dt2.microsecond, 0)
|
|
338
|
+
|
|
339
|
+
# ── 23. datetime.fromisoformat ───────────────────────────────────────────────
|
|
340
|
+
# STATUS: ✓ WORKS
|
|
341
|
+
|
|
342
|
+
_dti = datetime.fromisoformat('2024-01-15T09:30:45')
|
|
343
|
+
ae(_dti.year, 2024)
|
|
344
|
+
ae(_dti.hour, 9)
|
|
345
|
+
ae(_dti.minute, 30)
|
|
346
|
+
ae(_dti.second, 45)
|
|
347
|
+
|
|
348
|
+
_dti2 = datetime.fromisoformat('2024-01-15 09:30:45.123456')
|
|
349
|
+
ae(_dti2.microsecond, 123456)
|
|
350
|
+
|
|
351
|
+
_dti3 = datetime.fromisoformat('2024-01-15')
|
|
352
|
+
ae(_dti3.hour, 0)
|
|
353
|
+
ae(_dti3.minute, 0)
|
|
354
|
+
|
|
355
|
+
# ── 24. datetime.isoformat / str / repr ──────────────────────────────────────
|
|
356
|
+
# STATUS: ✓ WORKS
|
|
357
|
+
|
|
358
|
+
_dt3 = datetime(2024, 1, 15, 9, 30, 45)
|
|
359
|
+
ae(_dt3.isoformat(), '2024-01-15T09:30:45')
|
|
360
|
+
ae(_dt3.isoformat(' '), '2024-01-15 09:30:45')
|
|
361
|
+
ae(str(_dt3), '2024-01-15 09:30:45')
|
|
362
|
+
ae(repr(_dt3), 'datetime.datetime(2024, 1, 15, 9, 30, 45)')
|
|
363
|
+
|
|
364
|
+
_dt4 = datetime(2024, 1, 15, 9, 30, 45, 123456)
|
|
365
|
+
ae(repr(_dt4), 'datetime.datetime(2024, 1, 15, 9, 30, 45, 123456)')
|
|
366
|
+
|
|
367
|
+
# ── 25. datetime.combine ─────────────────────────────────────────────────────
|
|
368
|
+
# STATUS: ✓ WORKS
|
|
369
|
+
|
|
370
|
+
_dc = datetime.combine(date(2024, 1, 15), time(9, 30))
|
|
371
|
+
ae(_dc.year, 2024)
|
|
372
|
+
ae(_dc.month, 1)
|
|
373
|
+
ae(_dc.day, 15)
|
|
374
|
+
ae(_dc.hour, 9)
|
|
375
|
+
ae(_dc.minute, 30)
|
|
376
|
+
|
|
377
|
+
# ── 26. datetime.date() / datetime.time() ─────────────────────────────────────
|
|
378
|
+
# STATUS: ✓ WORKS
|
|
379
|
+
|
|
380
|
+
_dt5 = datetime(2024, 1, 15, 9, 30, 45)
|
|
381
|
+
_dt5_date = _dt5.date()
|
|
382
|
+
_dt5_time = _dt5.time()
|
|
383
|
+
ok(isinstance(_dt5_date, date))
|
|
384
|
+
ok(not isinstance(_dt5_date, datetime))
|
|
385
|
+
ok(isinstance(_dt5_time, time))
|
|
386
|
+
ae(_dt5_date.year, 2024)
|
|
387
|
+
ae(_dt5_time.hour, 9)
|
|
388
|
+
|
|
389
|
+
# ── 27. datetime arithmetic (direct method calls) ─────────────────────────────
|
|
390
|
+
# STATUS: ✓ WORKS
|
|
391
|
+
|
|
392
|
+
_dt_base = datetime(2024, 1, 15, 12, 0, 0)
|
|
393
|
+
|
|
394
|
+
# + timedelta
|
|
395
|
+
_dt_plus = _dt_base.__add__(timedelta(1))
|
|
396
|
+
ae(_dt_plus.year, 2024)
|
|
397
|
+
ae(_dt_plus.month, 1)
|
|
398
|
+
ae(_dt_plus.day, 16)
|
|
399
|
+
ae(_dt_plus.hour, 12)
|
|
400
|
+
|
|
401
|
+
# - timedelta
|
|
402
|
+
_dt_minus = _dt_base.__sub__(timedelta(0, 3600)) # subtract 1 hour
|
|
403
|
+
ae(_dt_minus.day, 15)
|
|
404
|
+
ae(_dt_minus.hour, 11)
|
|
405
|
+
|
|
406
|
+
# - datetime → timedelta
|
|
407
|
+
_dt_other = datetime(2024, 1, 10, 12, 0, 0)
|
|
408
|
+
_dt_diff = _dt_base.__sub__(_dt_other)
|
|
409
|
+
ok(isinstance(_dt_diff, timedelta))
|
|
410
|
+
ae(_dt_diff.days, 5)
|
|
411
|
+
ae(_dt_diff.seconds, 0)
|
|
412
|
+
|
|
413
|
+
# Cross-midnight arithmetic
|
|
414
|
+
_dt_night = datetime(2024, 1, 15, 23, 30, 0)
|
|
415
|
+
_dt_next = _dt_night.__add__(timedelta(0, 3600)) # +1 hour → next day
|
|
416
|
+
ae(_dt_next.day, 16)
|
|
417
|
+
ae(_dt_next.hour, 0)
|
|
418
|
+
ae(_dt_next.minute, 30)
|
|
419
|
+
|
|
420
|
+
# Cross-month
|
|
421
|
+
_dt_jan31 = datetime(2024, 1, 31, 23, 0, 0)
|
|
422
|
+
_dt_feb1 = _dt_jan31.__add__(timedelta(0, 3600))
|
|
423
|
+
ae(_dt_feb1.month, 2)
|
|
424
|
+
ae(_dt_feb1.day, 1)
|
|
425
|
+
ae(_dt_feb1.hour, 0)
|
|
426
|
+
|
|
427
|
+
# ── 28. datetime comparisons ──────────────────────────────────────────────────
|
|
428
|
+
# STATUS: ✓ WORKS
|
|
429
|
+
|
|
430
|
+
_dta = datetime(2024, 1, 1, 0, 0, 0)
|
|
431
|
+
_dtb = datetime(2024, 1, 1, 0, 0, 1)
|
|
432
|
+
_dtc = datetime(2024, 1, 1, 0, 0, 0)
|
|
433
|
+
|
|
434
|
+
ok(_dta.__eq__(_dtc))
|
|
435
|
+
ok(not _dta.__eq__(_dtb))
|
|
436
|
+
ok(_dta.__lt__(_dtb))
|
|
437
|
+
ok(_dtb.__gt__(_dta))
|
|
438
|
+
ok(_dta.__le__(_dtc))
|
|
439
|
+
ok(_dtb.__ge__(_dtb))
|
|
440
|
+
|
|
441
|
+
# ── 29. datetime.replace ─────────────────────────────────────────────────────
|
|
442
|
+
# STATUS: ✓ WORKS
|
|
443
|
+
|
|
444
|
+
_dt_r = datetime(2024, 1, 15, 9, 30, 0)
|
|
445
|
+
_dt_r2 = _dt_r.replace(hour=17, minute=0)
|
|
446
|
+
ae(_dt_r2.year, 2024)
|
|
447
|
+
ae(_dt_r2.month, 1)
|
|
448
|
+
ae(_dt_r2.day, 15)
|
|
449
|
+
ae(_dt_r2.hour, 17)
|
|
450
|
+
ae(_dt_r2.minute, 0)
|
|
451
|
+
|
|
452
|
+
# ── 30. datetime.strftime ────────────────────────────────────────────────────
|
|
453
|
+
# STATUS: ✓ WORKS
|
|
454
|
+
|
|
455
|
+
_dtf = datetime(2024, 1, 15, 14, 5, 9)
|
|
456
|
+
ae(_dtf.strftime('%Y-%m-%d %H:%M:%S'), '2024-01-15 14:05:09')
|
|
457
|
+
ae(_dtf.strftime('%A, %B %d, %Y'), 'Monday, January 15, 2024')
|
|
458
|
+
ae(_dtf.strftime('%I:%M %p'), '02:05 PM')
|
|
459
|
+
|
|
460
|
+
# ── 31. datetime class min/max/resolution ────────────────────────────────────
|
|
461
|
+
# STATUS: ✓ WORKS
|
|
462
|
+
|
|
463
|
+
ok(isinstance(datetime.min, datetime))
|
|
464
|
+
ok(isinstance(datetime.max, datetime))
|
|
465
|
+
ae(datetime.min.year, MINYEAR)
|
|
466
|
+
ae(datetime.max.year, MAXYEAR)
|
|
467
|
+
ae(datetime.max.hour, 23)
|
|
468
|
+
ae(datetime.max.microsecond, 999999)
|
|
469
|
+
|
|
470
|
+
# ── 32. isinstance and subclass checks ───────────────────────────────────────
|
|
471
|
+
# STATUS: ✓ WORKS
|
|
472
|
+
|
|
473
|
+
ok(isinstance(date(2024, 1, 1), date))
|
|
474
|
+
ok(isinstance(datetime(2024, 1, 1), date)) # datetime IS-A date
|
|
475
|
+
ok(isinstance(datetime(2024, 1, 1), datetime))
|
|
476
|
+
ok(not isinstance(date(2024, 1, 1), datetime)) # date is NOT-A datetime
|
|
477
|
+
ok(isinstance(time(12, 0), time))
|
|
478
|
+
ok(isinstance(timedelta(1), timedelta))
|
|
479
|
+
|
|
480
|
+
# ── 33. date.ctime ───────────────────────────────────────────────────────────
|
|
481
|
+
# STATUS: ✓ WORKS
|
|
482
|
+
|
|
483
|
+
ae(date(2024, 1, 15).ctime(), 'Mon Jan 15 00:00:00 2024')
|
|
484
|
+
|
|
485
|
+
# ── 34. datetime.ctime ───────────────────────────────────────────────────────
|
|
486
|
+
# STATUS: ✓ WORKS
|
|
487
|
+
|
|
488
|
+
ae(datetime(2024, 1, 15, 9, 5, 3).ctime(), 'Mon Jan 15 09:05:03 2024')
|
|
489
|
+
|
|
490
|
+
# ── 35. Validation errors ────────────────────────────────────────────────────
|
|
491
|
+
# STATUS: ✓ WORKS
|
|
492
|
+
# assrt.throws(fn) returns undefined on success; call it directly (not ok-wrapped)
|
|
493
|
+
|
|
494
|
+
throws(def(): date(0, 1, 1);) # year < MINYEAR
|
|
495
|
+
throws(def(): date(2024, 0, 1);) # month < 1
|
|
496
|
+
throws(def(): date(2024, 13, 1);) # month > 12
|
|
497
|
+
throws(def(): date(2023, 2, 29);) # Feb 29 in non-leap year
|
|
498
|
+
throws(def(): time(24, 0, 0);) # hour > 23
|
|
499
|
+
throws(def(): time(0, 60, 0);) # minute > 59
|
|
500
|
+
throws(def(): datetime(2024, 1, 1, 0, 0, 60);) # second > 59
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# globals: assrt
|
|
3
|
+
|
|
4
|
+
ae = assrt.equal
|
|
5
|
+
ok = assrt.ok
|
|
6
|
+
|
|
7
|
+
# debugger statement is a no-op when no debugger is attached; verify it
|
|
8
|
+
# compiles and executes without throwing
|
|
9
|
+
|
|
10
|
+
before = 1
|
|
11
|
+
debugger
|
|
12
|
+
after = 2
|
|
13
|
+
|
|
14
|
+
ae(before, 1)
|
|
15
|
+
ae(after, 2)
|
|
16
|
+
|
|
17
|
+
# inside a function
|
|
18
|
+
def fn_with_debugger():
|
|
19
|
+
x = 10
|
|
20
|
+
debugger
|
|
21
|
+
return x
|
|
22
|
+
|
|
23
|
+
ae(fn_with_debugger(), 10)
|
|
24
|
+
|
|
25
|
+
# inside a loop
|
|
26
|
+
total = 0
|
|
27
|
+
for i in range(3):
|
|
28
|
+
debugger
|
|
29
|
+
total += i
|
|
30
|
+
|
|
31
|
+
ae(total, 3)
|
|
32
|
+
|
|
33
|
+
# inside a conditional
|
|
34
|
+
def conditional_debugger(flag):
|
|
35
|
+
if flag:
|
|
36
|
+
debugger
|
|
37
|
+
return True
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
ae(conditional_debugger(True), True)
|
|
41
|
+
ae(conditional_debugger(False), False)
|
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())
|