Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/python-wasm
Path: blob/main/python/pylang/test/classes.py
1396 views
1
# globals: assrt
2
3
# empty classes are allowed
4
class Blank:
5
pass
6
blank = Blank()
7
assrt.ok(isinstance(blank, Blank))
8
9
# basic class
10
class Human:
11
12
HAIRS = 23
13
14
def __init__(self, name):
15
self.name = name
16
17
def greet(self):
18
return "Hello, I'm " + self.name
19
20
@staticmethod
21
def getTypicalWeight():
22
return "150"
23
24
@staticmethod
25
def with_arg(x):
26
return x
27
28
29
# don't have to declare __init__, it either gets inherited or stays empty
30
# isinstance correctly sees inheritance
31
class Friend(Human):
32
def greet(self):
33
return "Yo, it's me, " + self.name
34
35
def nickname(self, name):
36
self.name = name
37
38
# __init__ doesn't have to come first
39
# can call methods of other classes
40
class OldFriend(Friend):
41
def how_long(self):
42
return "I've known you for " + self.duration + " years"
43
def get_bound_method(self):
44
return self.how_long.bind(self)
45
def __init__(self, name, duration):
46
self.duration = duration
47
Friend.__init__(self, name)
48
49
bob = Human("Bob")
50
assrt.equal(bob.greet(), "Hello, I'm Bob")
51
assrt.equal(Human.greet(bob), "Hello, I'm Bob")
52
assrt.equal(Human.getTypicalWeight(), "150") # static method recognition
53
assrt.equal(Human.with_arg(3), 3) # static method with arg
54
assrt.equal(Human.HAIRS, 23)
55
56
joe = Friend("Joe")
57
assrt.equal(joe.greet(), "Yo, it's me, Joe")
58
assrt.ok(isinstance(joe, Friend))
59
assrt.ok(isinstance(joe, Human))
60
61
angela = OldFriend("Angela", 8)
62
assrt.equal(angela.greet(), "Yo, it's me, Angela")
63
assrt.equal(angela.how_long(), "I've known you for 8 years")
64
65
# test that function stays bound
66
bound = angela.get_bound_method()
67
assrt.equal(bound(), angela.how_long())
68
69
# function methods
70
assrt.deepEqual(dir(angela).sort(), [
71
'HAIRS',
72
"__init__",
73
'__repr__',
74
'__str__',
75
"constructor",
76
"duration",
77
"get_bound_method",
78
"greet",
79
"how_long",
80
"name",
81
"nickname",
82
])
83
84
# test that binding works in relation to the actual class, not the parent
85
angela.nickname("Angie")
86
assrt.equal(angela.greet(), "Yo, it's me, Angie")
87
88
dude = None
89
(def fake_module():
90
# test that we can declare classes inside other blocks
91
# test that we can call methods of classes we didn't inherit from
92
nonlocal dude
93
class Stranger(Human):
94
def greet(self):
95
return Friend.greet(self)
96
dude = Stranger("some guy")
97
)()
98
assrt.equal(dude.greet(), "Yo, it's me, some guy")
99
# also test that classes declared this way are not globally scoped (while normal ones are)
100
assrt.throws(
101
def():
102
Friend("another friend")
103
Stranger("another guy") # noqa:undef
104
,
105
/Stranger is not defined/
106
)
107
108
# attributes
109
assrt.ok(hasattr(dude, "greet"))
110
assrt.equal(getattr(dude, "greet").bind(dude)(), "Yo, it's me, some guy") # function stays bound after binding
111
assrt.equal(hasattr(dude, "stuff"), False)
112
setattr(dude, "stuff", True)
113
assrt.ok(hasattr(dude, "stuff"))
114
115
# native classes and methods
116
st = String("test")
117
assrt.equal(st, "test")
118
assrt.equal(st.toUpperCase(), "TEST")
119
assrt.equal(String.toUpperCase(st), "TEST")
120
assrt.equal(String.fromCharCode(65), "A") # static method recognition
121
122
# now we test PyLang's ability to insert 'new' operator correctly
123
assrt.ok(String('a') != 'a') # string literal vs string object
124
assrt.ok((String)('a') == 'a') # string literal vs string literal
125
assrt.ok(String.call(this, 'a') == 'a') # string literal via static method on string
126
127
# self consistency
128
class Counter:
129
def __init__(s, n=0):
130
s.count = n # first arg becomes 'self'
131
def getIncrementer(self):
132
return def():
133
self.count += 1
134
c = Counter(5)
135
inc = c.getIncrementer()
136
inc()
137
assrt.equal(c.count, 6)
138
139
# nested classes
140
# not yet fully implemented
141
#class Molecule:
142
# class Atom:
143
# def __init__(self, element):
144
# self.element = element
145
#
146
# def __init__(self, elements):
147
# self.structure = []
148
# for e in elements:
149
# self.structure.push(Molecule.Atom(e))
150
#
151
#water = Molecule(['H', "H", 'O'])
152
#assrt.equal(len(water.structure), 3)
153
#assrt.equal(water.structure[0].element, 'H')
154
#for atom in water.structure:
155
# assrt.ok(isinstance(atom, Molecule.Atom))
156
157
# starargs and method decorators
158
def negate(fn):
159
def wrapped(*args):
160
return -fn(*args)
161
return wrapped
162
163
def add_pi(cls):
164
cls.prototype.pi = 3.14
165
return cls
166
167
@add_pi
168
class Math:
169
def sum(s, *args):
170
# fakearg simply tests that offsets work correctly
171
ttl = 0
172
for i in args:
173
ttl += i
174
return ttl
175
def concatSum(s, string, *nums):
176
return string + s.sum(*nums)
177
@negate
178
def plus(s, a, b):
179
return a+b
180
181
m = Math()
182
assrt.equal(m.sum(1,2,3), 6)
183
assrt.equal(m.sum(1,*[2,3]), 6)
184
assrt.equal(m.concatSum("foo", 1, 2, 5), "foo8")
185
assrt.equal(m.plus(2, 5), -7)
186
assrt.equal(m.pi, 3.14)
187
188
189
class CV():
190
191
a = b = 1
192
c = a + b
193
if True:
194
d = 1
195
else:
196
d = 2
197
198
def one(self):
199
return 1
200
two = one
201
202
c = CV()
203
assrt.deepEqual([c.a, c.b, c.c, c.d], [1, 1, 2, 1])
204
assrt.equal(c.one(), c.two())
205
206
207
class Properties:
208
209
def __init__(self):
210
self._a = 19
211
assrt.equal(self.a, 19)
212
213
@property
214
def a(self):
215
return self._a
216
217
@a.setter
218
def a(self, val):
219
self._a = val
220
221
@property
222
def b(self):
223
return 1
224
225
def c(self):
226
return self.a
227
228
class A:
229
@property
230
def val(self):
231
return 'a'
232
233
@property
234
def parent(self):
235
return 'parent'
236
237
class B(A):
238
@property
239
def val(self):
240
return 'b'
241
242
243
p = Properties()
244
assrt.equal(p._a, p.a)
245
p.a = 11
246
assrt.equal(11, p.a)
247
assrt.equal(p.c(), p.a)
248
assrt.equal(p.b, 1)
249
assrt.throws(
250
def():
251
p.b = 2
252
)
253
p = B()
254
assrt.equal(p.val, 'b')
255
assrt.equal(p.parent, 'parent')
256
assrt.equal(id(p), id(p))
257
assrt.notEqual(id(p), id(B()))
258
259
class Context:
260
261
val = 1
262
263
def __enter__(self):
264
self.val = 2
265
return self
266
267
def __exit__(self):
268
self.val = 3
269
return True
270
271
with Context() as c:
272
assrt.eq(c.val, 2)
273
274
assrt.equal(c.val, 3)
275
276
with Context() as d:
277
assrt.equal(d.val, 2)
278
raise Exception('error')
279
assrt.equal(d.val, 3)
280
281
282
class Throws:
283
284
def __enter__(self):
285
pass
286
287
def __exit__(self):
288
pass
289
290
assrt.throws(
291
def ():
292
with Throws():
293
raise Exception('error')
294
, Exception
295
)
296
297
class X:
298
299
def __init__(self):
300
self.a = 3
301
302
class Y(X):
303
pass
304
305
class Z(Y):
306
pass
307
308
assrt.equal(Z().a, X().a)
309
assrt.ok(repr(Z()).indexOf('<__main__.Z') == 0)
310
assrt.ok(str(Z()).indexOf('<__main__.Z') == 0)
311
312
from __python__ import bound_methods
313
314
class U:
315
316
def __init__(self, a):
317
self.a = a
318
319
def val(self):
320
return self.a
321
322
u = U(3)
323
f = u.val
324
assrt.equal(f(), u.val())
325
326
class U2(U):
327
328
def val(self):
329
return self.a * 2
330
331
u = U2(3)
332
f = u.val
333
assrt.equal(f(), 6)
334
335
class M1:
336
337
def f1(self):
338
return 'M1-f1'
339
340
def f3(self):
341
return 'M1-f3'
342
343
class M0:
344
345
def f0(self):
346
return 'M0-f0'
347
348
class M2(M0):
349
350
@property
351
def prop(self):
352
return self._p or 'prop'
353
354
@prop.setter
355
def prop(self, val):
356
self._p = val
357
358
def f1(self):
359
return 'M2-f1'
360
361
def f2(self):
362
return 'M2-f2'
363
364
def f3(self):
365
return 'M2-f3'
366
367
class Child(M1, M2):
368
369
def f3(self):
370
return 'Child-f3'
371
372
c = Child()
373
assrt.equal(c.f0(), 'M0-f0')
374
assrt.equal(c.f1(), 'M1-f1')
375
assrt.equal(c.f2(), 'M2-f2')
376
assrt.equal(c.f3(), 'Child-f3')
377
assrt.equal(c.prop, 'prop')
378
c.prop = 1
379
assrt.equal(c.prop, 1)
380
assrt.ok(isinstance(c, Child))
381
assrt.ok(isinstance(c, M1))
382
assrt.ok(isinstance(c, M2))
383
assrt.ok(isinstance(c, M0))
384
385
386
class B1:
387
388
def __init__(self):
389
self.b1 = 1
390
391
def one(self):
392
return self.two()
393
394
def two(self):
395
return self.b1
396
397
class B2(B1):
398
399
def __init__(self):
400
self.b2 = 2
401
B1.__init__(self)
402
403
def two(self):
404
return self.b2
405
assrt.equal(B2().two(), 2)
406
assrt.equal(B2().b1, 1)
407
408
409
class Cvar:
410
a = b = 0
411
def __init__(self):
412
Cvar.a += 1
413
414
def inc(self):
415
Cvar.a += 1
416
417
def val(self):
418
return Cvar.a
419
420
def incb(self):
421
Cvar.b += 1
422
return Cvar.b
423
424
assrt.equal(Cvar.a, 0)
425
c = Cvar()
426
assrt.equal(Cvar.a, 1)
427
c.inc()
428
assrt.equal(Cvar.a, 2)
429
assrt.equal(Cvar().val(), 3)
430
assrt.equal(Cvar().incb(), 1)
431
assrt.equal(Cvar().incb(), 2)
432
433
class anon_func_in_class:
434
435
f = def():
436
func_var = 1
437
return func_var
438
439
def func_var(self):
440
pass
441
442
assrt.equal(jstype(anon_func_in_class.prototype.func_var), 'function')
443
anon_func_in_class.prototype.f()
444
assrt.equal(jstype(anon_func_in_class.prototype.func_var), 'function')
445
446
447
def decorate(cls):
448
assrt.equal(cls.prototype.somevar, 1)
449
return cls
450
451
452
@decorate
453
class decorated:
454
somevar = 1
455
456