# 4. Systematic code examples: a guided tour of Transcrypt

One ready-to-run code example is worth more than ten lengthy descriptions. The autotest and demo suite, that is part of the distribution, is a collection of sourcecode fragments called testlets. These testlets are used for automated regression testing of Transcrypt against CPython. Since they systematically cover all language constructs, they are also very effective as a learning tool. The testlets are arranged alphabetically by subject.

Autotest: Transcrypt autotest demo suite

    import org.transcrypt.autotester

    import arguments
    import classes
    import conditional_expressions
    import control_structures
    import data_structures
    import dictionaries
    import exceptions
    import general_functions
    import indices_and_slices
    import lambda_functions
    import list_comprehensions
    import modules
    import operator_overloading
    import properties
    import simple_and_augmented_assignment
    import tuple_assignment

    autoTester = org.transcrypt.autotester.AutoTester ()

    autoTester.run (arguments, 'arguments')
    autoTester.run (classes, 'classes')
    autoTester.run (conditional_expressions, 'conditional_expressions')
    autoTester.run (control_structures, 'control_structures')
    autoTester.run (data_structures, 'data_structures')
    autoTester.run (dictionaries, 'dictionaries')
    autoTester.run (exceptions, 'exceptions')
    autoTester.run (general_functions, 'general_functions')
    autoTester.run (indices_and_slices, 'indices_and_slices')
    autoTester.run (lambda_functions, 'lambda_functions')
    autoTester.run (list_comprehensions, 'list_comprehensions')
    autoTester.run (modules, 'modules')
    autoTester.run (operator_overloading, 'operator_overloading')
    autoTester.run (properties, 'properties')
    autoTester.run (simple_and_augmented_assignment, 'simple_and_augmented_assignment')
    autoTester.run (tuple_assignment, 'tuple_assignemt')

    autoTester.done ()

## 4.1. Arguments: **kwargs, *args, defaults, at call and def time, also for lambda’s

Testlet: arguments

    from org.transcrypt.stubs.browser import __pragma__

    __pragma__ ('kwargs')

    class A:
        def __init__ (self, x = 123, y = 456, *args, m, n = 456, **kwargs):
            self.x = x
            self.y = y
            self.args = args
            self.m = m
            self.n = n
            self.kwargs = kwargs
            self.extra = 'hello'

        def f (self, autoTester):
            autoTester.check (self.x, self.y, self.args, self.m, self.n, self.kwargs, self.extra)

    class B (A):
        def __init__ (self, x, y = -1, *args, m = -2, n, **kwargs):
            A.__init__ (self, y, x, *args, m = n, n = m, **kwargs)

    class C:
        __pragma__ ('nokwargs')
        def tricky (self, *args):
            return args
        __pragma__ ('kwargs')

    def run (autoTester):
        def f (x, y = -1, *args, m = -2, n, **kwargs):
            def f2 (x, y = -3, *args, m = -4, n, **kwargs):
                autoTester.check (x, y, args, m, n, kwargs)
            f2 (11, 22, 1010, 2020, m = 100100, n = 200200, p = 10001000, q = 20002000)
            autoTester.check (x, y, args, m, n, kwargs)

        f (1, 2, 10, 20, m = 100, n = 200, p = 1000, q = 2000)

        b = B (3, 4, 30, 40, m = 300, n = 400, p = 3000, q = 4000)
        b.f (autoTester)

        def g (*args, **kwargs):
            autoTester.check (args, kwargs)

        g (*(1, 2, 3), **{'p': 'aP', 'q': 'aQ', 'r': 'anR'})

        (lambda x, y = -1, *args, m = -2, n, **kwargs: autoTester.check (x, y, args, m, n, kwargs)) (1, 2, 8, 16, m = 128, n = 256.3, p = 1024.3, q = 2048.3)

        autoTester.check (C () .tricky (* range (4)))
        autoTester.check ('{}-{}'.format (1, 3, 5, 7, 9))
        autoTester.check ('{}-{}'.format (* range (4)))

## 4.2. Classes: multiple inheritance and assignment of bound functions

Testlet: classes

    def run (autoTester):
        class A:
            p = 123
            def __init__ (self, x):
                self.x = x
                autoTester.check (self.p)

            def show (self, label):
                autoTester.check ('A.show', label, self.x)

            def show2 (self, label):
                autoTester.check ('A.show2', label, self.x)

        class B:
            p, q = 456, 789
            def __init__ (self, y):
                autoTester.check ('In B constructor')
                self.y = y
                autoTester.check (self.p)

            def show (self, label):
                autoTester.check ('B.show', label, self.y)

        class C (A, B):
            def __init__ (self, x, y):
                autoTester.check ('In C constructor')
                A.__init__ (self, x)
                B.__init__ (self, y)

            def show (self, label):
                A.show (self, label)
                B.show (self, label)
                autoTester.check ('C.show', label, self.x, self.y)

        a = A (1001)
        a.show ('america')
        autoTester.check (A.p)
        autoTester.check (a.p)

        b = B (2002)
        b.show ('russia')
        autoTester.check (B.p)
        autoTester.check (b.p)
        autoTester.check (b.q)

        autoTester.check (A.p)
        autoTester.check (a.p)

        c = C (3003, 4004)
        c.show ('netherlands')
        autoTester.check (C.p)
        autoTester.check (c.p)
        autoTester.check (c.q)

        c.show2 ('amsterdam')
        A.show2 (c, 'rotterdam')

        show3 = c.show
        show3 ('copy')

## 4.3. Conditional expressions: simple and nested

Testlet: conditional_expressions

    def f (x, b):
        return x * x if b else x + x

    def run (autoTester):
        bools = (False, True)
        for a in bools:
            for b in bools:
                autoTester.check (f (10 if a else 100, b))

        for p in bools:
            for q in bools:
                for r in bools:
                    autoTester.check ('a' if p else 'b' if q else 'c' if r else 'd')

                    a = ((('e' if p else 'f') if q else 'g') if r else 'h')
                    b = ('i' if p else ('j' if q else ('k' if r else 'l')))
                    c = 'm' if (p if q else r) else 'n'
                    d = 'o' if p < q <= r else 'p'
                    autoTester.check (a, b, c, d)

        odd = [x if x % 2 else x + 1 for x in range (10)]
        noDuplicates = set (odd)
        autoTester.check (odd, noDuplicates)

## 4.4. Control structures: for...else, while...else, if...elif...else, break, continue

Testlet: control_structures

    def run (autoTester):
        for index, square in enumerate ([x * x for x in range (10) if x % 2]):
            for y in range (1, 2, 3):
                for z in range (10, 20, 30):
                    autoTester.check (square + y, z )

        vehicles = ['bike', 'train', 'boat', 'car', 'plane', 'bus']

        for doBreak in (False, True):
            for doContinue in (False, True):
                for index in range (10):
                    for index2 in range (0, 100, 10):
                        if doBreak and index2 == 50:
                            autoTester.check ('break2')
                            break
                        if doContinue and index2 == 50:
                            autoTester.check ('continue2')
                            continue
                    else:
                        autoTester.check ('noBreak2')

                    if doBreak and index == 5:
                        autoTester.check ('break')
                        break
                    if doContinue and index == 5:
                        autoTester.check ('continue')
                        continue
                else:
                    autoTester.check ('noBreak')

                index = 0
                while index < len (vehicles) and vehicles [index] != 'bus':
                    autoTester.check (index, vehicles [index])
                    if doBreak and vehicles [index] == 'car':
                        autoTester.check ('breakWhile')
                        break
                    if doContinue and vehicles [index] == 'car':
                        autoTester.check ('continueWhile')
                        index += 1
                        continue
                    index += 1
                else:
                    autoTester.check ('noBreakWhile')

            for vehicle in vehicles:
                if vehicle == 'bike':
                    autoTester.check ('netherlands')
                elif vehicle == 'car':
                    autoTester.check ('america')
                elif vehicle == 'boat':
                    autoTester.check ('oceania')
                else:
                    autoTester.check ('anywhere')

## 4.5. Data structures: tuple, list, dict, set

Testlet: data_structures

    def run (autoTester):
        aList = [1, 2, 3, 'sun', 'moon', 'stars']
        autoTester.check (aList)
        autoTester.check (aList [2:4:1])
        autoTester.check (aList [:])
        autoTester.check (aList [2:])
        autoTester.check (len (aList))
        aList.append ('milkyway')
        autoTester.check (aList)
        aList.extend (['m1', 'm31'])
        autoTester.check (aList)

        anotherList = list (('a', 'b', 'c'))
        autoTester.check (anotherList)

        aDict = {1: 'plant', 'animal': 2}
        autoTester.check (aDict)
        autoTester.check (aDict [1], aDict ['animal'])

        def p ():
            return 3

        q = 4

        autoTester.check ({p (): 'three', q: 'four'})

        aTuple = (1, 2, 3, 4, 5)
        autoTester.check(aTuple)
        autoTester.check (len (aTuple))

        anotherTuple = (1,)
        autoTester.check (anotherTuple)

        aSet = {1, 2, 2, 3}
        autoTester.check    (aSet)
        autoTester.check (len (aSet))

        anotherSet = set ((4, 5, 5, 6))
        autoTester.check (anotherSet)

        emptySet = set ()
        autoTester.check (emptySet)
        autoTester.check (len (emptySet))

## 4.6. Dictionaries: dict revisited

Testlet: dictionaries

    from org.transcrypt.stubs.browser import __pragma__
    __pragma__ ('iconv')

    def run (autoTester):
        tel = {'guido': 4127, 'jack': 4098}
        tel ['sape'] = 4139

        autoTester.check (tel)
        autoTester.check (tel ['jack'])

        del tel ['sape']
        tel ['irv'] = 4127
        autoTester.check (tel)

        autoTester.check (sorted (list (tel.keys ())), False)
        autoTester.check (sorted (tel.keys ()))

        autoTester.check ('guido' in tel)
        autoTester.check ('jack' not in tel)

        autoTester.check (dict ([('guido', 4127), ('jack', 4098), ('sape', 4139)]))

        knights = {'robin': 'the brave', 'gallahad': 'the pure'}

        for k, v in sorted (knights.items ()):
            autoTester.check (k, v)

        if 'gallahad' in knights:
            autoTester.check ('gallahad is a knight')

        for k in sorted (knights):
            autoTester.check (k)

        knight = {'rudolph': 'the righteous'}
        for k in knight:    # Autotest automatic conversion with one knight, since sort order of dict undefined
            autoTester.check (k)

## 4.7. Exceptions: exception class hierarchy, finally

Testlet: exceptions

    class Ex1 (Exception):
        pass

    class Ex2 (Ex1):
        pass

    class Ex3 (Exception):
        pass

    def test1 ():
        raise (Exception ('mary'))

    def test2 (autoTester):
        try:
            test1 ()
        except Ex1 as exception:
            autoTester.check (111)
            autoTester.check (exception)
        except Exception as exception:
            autoTester.check (222)
            autoTester.check (exception)

    def run (autoTester):
        test2 (autoTester)

        try:
            raise Ex2 ('had')
        except Ex1 as exception:
            autoTester.check ('a')
        except Exception as exception:
            autoTester.check ('little')
            autoTester.check (exception)

        autoTester.check (333)

        try:
            raise Ex1 ('lamb')
        except Ex2 as exception:
            autoTester.check ('his')
            autoTester.check (exception)
        except Ex1 as exception:
            autoTester.check ('fleece')
            autoTester.check (exception)
        except Exception as exception:
            autoTester.check ('was')
            autoTester.check (exception)
        finally:
            autoTester.check ('white')

        autoTester.check (444)

        def test3 ():
            raise Ex3 ('as')

        autoTester.check (555)

        try:
            test3 ()
        except Ex1 as exception:
            autoTester.check ('snow')
            autoTester.check (exception)
        except Exception as exception:
            autoTester.check ('and')
            autoTester.check (exception)
        finally:
            autoTester.check ('everywhere')

        autoTester.check (666)

## 4.8. General functions: sort and sorted

Testlet: general_functions

    def run (autoTester):
        a = [1, 5, 3, 2, -1]
        b = ['sun', 'earth', 'moon']

        autoTester.check (sorted (a))
        autoTester.check (sorted (b))

        a.sort ()
        autoTester.check (a)

        b.sort ()
        autoTester.check (b)

        autoTester.check (sorted (a, reverse = True))
        autoTester.check (sorted (b, reverse = True))

        a.sort (reverse = True)
        autoTester.check (a)

        b.sort (reverse = True)
        autoTester.check (b)

        b.sort (key = lambda x: len (x))
        autoTester.check (b)

        b.sort (key = lambda x: len (x), reverse = True)
        autoTester.check (b)

## 4.9. Hierarchical modules: both local to the project and global url-based

Testlet: modules

    import modules.mod1.mod11.mod111
    import modules.mod3
    import modules.mod1.mod11.mod112
    import modules.mod1
    import modules.mod1.mod11
    import modules.mod2
    import modules.mod2.mod21
    import modules.mod2.mod22

    import modules.mod1.mod11.mod111 as aliasMod111
    import modules.mod1 as aMod1

    from modules.mod1.mod11 import mod111, mod112

    from modules.mod2 import mod21 as aMod21, mod22 as aMod22

    from modules.mod3 import *

    from modules.mod1.mod11.mod111 import A

    a = modules.mod1.mod11.mod111.A (12345)
    pi = modules.mod1.pi
    f = modules.mod2.f

    def run (autoTester):
        # Import without 'as'
        autoTester.check ('modules')
        autoTester.check (a.f ())
        autoTester.check (modules.mod1.mod11.mod112.f ())
        autoTester.check (modules.mod1.mod11.e)
        autoTester.check (pi)
        autoTester.check (f (102030))
        autoTester.check (modules.mod2.mod21.f ())
        B = modules.mod2.mod22.B
        b = B ()
        autoTester.check (b.x)
        autoTester.check (modules.mod3.x)

        # Import with 'as'
        a2 = aliasMod111.A (6789101112)
        autoTester.check (a2.f ())
        autoTester.check (aMod1.pi)

        # From ... import without 'as'
        a3 = mod111.A (100.001)
        autoTester.check (a3.f ())
        autoTester.check (mod112.f ())

        # From ... import with 'as'
        autoTester.check (aMod21.f ())
        autoTester.check (aMod22.B () .x)

        # From ... import *
        autoTester.check (mod3Hundred)
        autoTester.check (mod3GetTwoHundred ())
        autoTester.check (A (123.321) .f ())

## 4.10. Indices and slices: LHS, RHS, basic and extended

Testlet: indices_and_slices

    def run (autoTester):
        # Right hand side slices
        all = range (32)
        autoTester.check (all)

        autoTester.check (all [8 : 24])
        autoTester.check (all [8 : 24 : 2])

        # Left hand side slices
        aList = [3, 4, 7, 8]
        autoTester.check (aList)

        aList [4 : 4] = [9, 10]
        autoTester.check (aList)

        aList [2 : 2] = [5, 6]
        autoTester.check (aList)

        aList [0 : 0] = [1, 2]
        autoTester.check (aList)

        aList [ : : 2] = [x + 0.001 for x in range (10) if x % 2]
        autoTester.check (aList)

## 4.11. Lambda functions with all types of args

Testlet: lambda_functions

    def run (autoTester):
        z = 1000
        autoTester.check ((lambda x, y: x + y + z) (111, 222))

        def f (list0, list1, aFunc):
            return [aFunc (*elem) for elem in zip (list0, list1)]

        x = f (range (10), range (0, 100, 10), lambda x, y: x + y + z)
        autoTester.check (x)

        autoTester.check (f (range (10, 20), range (100, 200, 10), lambda x, y: x * y + 100 * z))
        autoTester.check (f (range (10, 20), range (100, 200, 10), lambda *args: args [0] * args [1] + 100 * z))

## 4.12. List comprehensions: multi-loop and nested with multiple if’s

Testlet: list_comprehensions

    def run (autoTester):
        squares = [i * i for i in range (10) if i % 2]
        autoTester.check (squares)

        tuples = [
            (x, y, z)
            for x in (100, 200, 300, 400, 500, 600, 700)
                for y in (10, 20, 30, 40, 50, 60, 70) if 20 < y  < 60
                    for z in (1, 2, 3, 4, 5, 6, 7) if 200 < x < 600 if 2 < z < 6
        ]
        autoTester.check (tuples)

        tricky = [(2 * x, 3 * y) for x, y in ((10, 11), (20, 21))]
        autoTester.check (tricky)

        nested = [2 * x for x in [x * x for x in range (3)]]
        autoTester.check (nested)

        a = 100
        x = 5
        scopeTest = [x + a for x in range (5)]
        autoTester.check (x)
        autoTester.check (scopeTest)

## 4.13. Operator overloading

Testlet: operator_overloading

    from org.transcrypt.stubs.browser import __pragma__

    class Matrix:
        def __init__ (self, nRows, nCols, elements = []):
            self.nRows = nRows
            self.nCols = nCols

            if len (elements):
                self._ = elements
            else:
                self._ = [[0 for col in range (nCols)] for row in range (nRows)]

        def __mul__ (self, other):
            if type (other) == Matrix:
                result = Matrix (self.nRows, other.nCols)
                for iTargetRow in range (result.nRows):
                    for iTargetCol in range (result.nCols):
                        for iTerm in range (self.nCols):
                            result._ [iTargetRow][iTargetCol] += self._ [iTargetRow][iTerm] * other._ [iTerm][iTargetCol]
                return result
            else:   # other is a scalar
                return self.__rmul__ (other)

        def __rmul__ (self, scalar):    # Only called if left operand is scalar, all other cases will call __mul__
            result = Matrix (self.nRows, self.nCols)
            for iRow in range (self.nRows):
                for iCol in range (self.nCols):
                    result._ [iRow][iCol] = scalar * self._ [iRow][iCol]
            return result

        def __add__ (self, other):
            result = Matrix (self.nRows, self.nCols)
            for iRow in range (self.nRows):
                for iCol in range (self.nCols):
                    result._ [iRow][iCol] = self._ [iRow][iCol] + other._ [iRow][iCol]
            return result

        def __getitem__ (self, index):
            return self._ [index]

        def __setitem__ (self, index, value):
            self._ [index] = value

        def __repr__ (self):
            return repr (self._)

    class Functor:
        def __init__ (self, factor):
            self.factor = factor

        __pragma__ ('kwargs')
        def __call__ (self, x, y = -1, *args, m = -2, n, **kwargs):
            return (
                self.factor * x,
                self.factor * y,
                [self.factor * arg for arg in args],
                self.factor * m,
                self.factor * n,
                # !!! [self.factor * kwargs [key] for key in sorted (kwargs.keys ())] Add supoprt for keys () on kwargs
            )
        __pragma__ ('nokwargs')

    f = Functor (10)

    __pragma__ ('kwargs')
    def g (x, y = -1, *args, m = -2, n, **kwargs):
        return (x, y, args, m, n) # !!! , [kwargs [key] for key in sorted (kwargs.keys ())]) Add support for keys () on kwargs
    __pragma__ ('nokwargs')

    def run (autoTester):
        m0 = Matrix (3, 3, [
            [1, 2, 3],
            [4, 5, 6],
            [7, 8, 10]
        ])

        m1 = Matrix (3, 3, [
            [10, 20, 30],
            [40, 50, 60],
            [70, 80, 90]
        ])

        x = 3
        y = x * 4 * x
        fast = 2 * 3

        __pragma__ ('opov')

        m1 [1][2] = m0 [1][2]
        slow = 2 + 3
        m2 = m0 * m1  + m1 * (m0 + m1)
        m3 = 2 * (2 * m0 * 3 * m1 + m2 * 4) * 2
        autoTester.check (m0 [1][1], m0 [1][2], m1 [1][1], m1 [1][2])

        __pragma__ ('noopov')

        fast2 = 16 * y + 1

        autoTester.check (m0, m1)
        autoTester.check (x, y)
        autoTester.check (m2)
        autoTester.check (m3)
        autoTester.check (fast, slow, fast2)

        x = 'marker'

        __pragma__ ('opov')
        autoTester.check (f (3, 4, 30, 40, m = 300, n = 400, p = 3000, q = 4000))
        autoTester.check (g (3, 4, 30, 40, m = 300, n = 400, p = 3000, q = 4000))
        __pragma__ ('noopov')

## 4.14. Properties

Testlet: properties

    class A:
        p = 1234
        def getX (self):
            return self._x

        def setX (self, value):
            self._x = value

        def getY (self):
            return self._y

        def setY (self, value):
            self._y = 1000 + value  # Weird but should be possible

        def getY2 (self):
            return self._y

        def setY2 (self, value):
            self._y = value

        def getT    (self):
            return self._t

        def setT (self, value):
            self._t = value

        def getU (self):
            return self._u + 10000

        def setU (self, value):
            self._u = value - 5000

        x, y, y2 = property (getX, setX), property (getY, setY), property (getY2, setY2)
        t = property (getT, setT)
        u = property (getU, setU)

    A.q = 5678

    class B:
        def getZ (self):
            return self.z_

        def setZ (self, value):
            self.z_ = value

        z = property (getZ, setZ)

    class C:
        def __init__ (self):
            self.offset = 1234

        def getW (self):
            return self.w_ + self.offset

        def setW (self, value):
            self.w_ = value - self.offset

        w = property (getW, setW)

    def run (autoTester):
        a1 = A ()
        a2 = A ()

        a1.y2 = 1000
        a2.y2 = 2000

        a1.x = 5
        a1.y = 6

        a2.x = 7
        a2.y = 8

        a1.t = 77
        a1.u = 88

        autoTester.check (a1.x, a1.y, a1.y2)
        autoTester.check (a2.x, a2.y, a2.y2)
        autoTester.check (a1.p, a2.p, a1.q, a2.q)

        autoTester.check (a1.t, a1.u)

        b = B ()
        c = C ()

        b.z = 100100
        c.z = 200200
        c.w = 300300

        autoTester.check (a1.x, b.z, c.z, c.w)

        c.w = 400400
        c.z = 500500
        b.z = 600600

        autoTester.check (a1.x, b.z, c.z, c.w)

## 4.15. Simple and augmented assignment

Testlet: simple_and_augmented_assignment

    class A:
        def __init__ (self):
            self.i = 0

        def f (self):
            return self.i

    a = A ()

    def run (autoTester):
        x = 3
        y = 5
        z = x + y
        autoTester.check (z)

        l = [1, 2, 3]
        l [1] = l [2]
        autoTester.check (l)

        # Should generate x++
        x += 1
        autoTester.check (x)
        x += +1
        autoTester.check (x)
        x -= -1
        autoTester.check (x)

        # Should generate y--
        y -= 1
        autoTester.check (y)
        y -= +1
        autoTester.check (y)
        y += -1
        autoTester.check (y)

        x += -3
        autoTester.check (x)

        x += 6
        autoTester.check (x)

        y -= 3
        autoTester.check (y)

        l [1] += l [1]
        autoTester.check (l)

        x += y
        y += x

        autoTester.check (x, y)

        f = a.f

        a.i += 1
        autoTester.check (f ())

        a.i += 10
        autoTester.check (f ())

        a.i += a.i
        autoTester.check (f ())

## 4.16. Tuple assignment: recursive and in for-headers using enumerate

Testlet: tuple_assignment

    def run (autoTester):
        ((a, b), santa, [c, d], e) = ((1, 2), 'santa-claus', {3, 4}, 5)
        autoTester.check (a, b, c, d, e, santa)

        for i, x in enumerate ((0.5, 1.5, 2.5, 3.5)):
            autoTester.check (i, x)

        e, pi = 3.14, 2.74
        e, pi = pi, e
        autoTester.check (e, pi)

        def f ():
            return [(i, 2 * i) for i in range (7000, 10000, 1000)]

        def g ():
            return f

        [k, l], [m, n], (o, p) = g () ()

        autoTester.check (k, l, m, n, o, p)