Beispiel #1
0
    def test_calling_method_from_init(self):

        # Note that all class names inside a module need to be unique
        # for js() to find the correct source.

        class MyClass11:
            def __init__(self):
                self._res = self.m1() + self.m2() + self.m3()

            def m1(self):
                return 100

            def m2(self):
                return 10

        class MyClass12(MyClass11):
            def m2(self):
                return 20

            def m3(self):
                return 2

        code = py2js(MyClass11) + py2js(MyClass12)
        assert evaljs(code + 'var m = new MyClass12(); m._res') == '122'
        assert evaljs(code + 'var m = new MyClass12(); m.m1()') == '100'
Beispiel #2
0
    def test_overload_truthy(self):
        def foo():
            PSCRIPT_OVERLOAD = False
            for v in [true, 0, "a", "", [], {}]:
                if v:
                    print('1')
                else:
                    print('0')
            return None or False

        js = py2js(foo)
        assert "PSCRIPT_OVERLOAD" not in js
        assert "pyfunc" not in js
        ans = '1', '0', '1', '0', '1', '1', 'false'
        assert evaljs(js + '\nfoo();') == '\n'.join(ans)

        def bar():
            PSCRIPT_OVERLOAD = False
            for v in [true, 0, "a", "", [], {}]:
                if v:
                    print('1' + bool(v))
                else:
                    print('0' + bool(v))
            return None or False

        js = py2js(bar)
        assert "PSCRIPT_OVERLOAD" not in js
        # assert "pyfunc" not in js  # bool() does pyfunc_truthy()
        ans = '1true', '0false', '1true', '0false', '1false', '1false', 'false'
        assert evaljs(js + '\nbar();') == '\n'.join(ans)
Beispiel #3
0
 def test_comparisons(self):
     
     assert py2js('4 > 3') == '4 > 3;'
     assert py2js('4 is 3') == '4 === 3;'
     
     assert evalpy('4 > 4') == 'false'
     assert evalpy('4 >= 4') == 'true'
     assert evalpy('4 < 3') == 'false'
     assert evalpy('4 <= 4') == 'true'
     assert evalpy('4 == 3') == 'false'
     assert evalpy('4 != 3') == 'true'
     
     assert evalpy('4 == "4"') == 'true'  # yuck!
     assert evalpy('4 is "4"') == 'false'
     assert evalpy('4 is not "4"') == 'true'
     
     assert evalpy('"c" in "abcd"') == 'true'
     assert evalpy('"x" in "abcd"') == 'false'
     assert evalpy('"x" not in "abcd"') == 'true'
     
     assert evalpy('3 in [1,2,3,4]') == 'true'
     assert evalpy('9 in [1,2,3,4]') == 'false'
     assert evalpy('9 not in [1,2,3,4]') == 'true'
     
     assert evalpy('"bar" in {"foo": 3}') == 'false'
     assert evalpy('"foo" in {"foo": 3}') == 'true'
     
     # was a bug
     assert evalpy('not (1 is null and 1 is null)') == 'true'
Beispiel #4
0
    def test_overload_scope(self):

        # Can turn on and off
        def foo():
            print({} or 'x')
            PSCRIPT_OVERLOAD = False
            print({} or 'x')
            PSCRIPT_OVERLOAD = True
            print({} or 'x')

        #
        js = py2js(foo)
        assert evaljs(js + '\nfoo();').replace('\n', ' ') == 'x {} x null'

        # Scoped per function
        def foo():
            def x1():
                print({} or 'x')

            def x2():
                PSCRIPT_OVERLOAD = False
                print({} or 'x')

            def x3():
                print({} or 'x')

            print({} or 'x')
            x1()
            x2()
            x3()
            print({} or 'x')

        #
        js = py2js(foo)
        assert evaljs(js + '\nfoo();').replace('\n', ' ') == 'x x {} x x null'

        # Scope is maintained
        def foo():
            PSCRIPT_OVERLOAD = False

            def x1():
                print({} or 'x')

            def x2():
                PSCRIPT_OVERLOAD = False
                print({} or 'x')

            def x3():
                print({} or 'x')

            print({} or 'x')
            x1()
            x2()
            x3()
            print({} or 'x')

        #
        js = py2js(foo)
        assert evaljs(js + '\nfoo();').replace('\n',
                                               ' ') == '{} x {} x {} null'
Beispiel #5
0
    def test_bound_methods(self):
        class MyClass14:
            def __init__(self):
                self.a = 1

            def add2(self):
                self.a += 2

        class MyClass15(MyClass14):
            def add3(self):
                self.a += 3

        code = py2js(MyClass14) + py2js(MyClass15)
        assert evaljs(
            code + 'var m = new MyClass14(); m.add2(); m.add2(); m.a') == '5'
        assert evaljs(
            code +
            'var m = new MyClass14(); var f = m.add2; f(); f(); m.a') == '5'
        assert evaljs(
            code +
            'var m = new MyClass15(); var f = m.add3; f(); f(); m.a') == '7'
        assert evaljs(
            code +
            'var m = new MyClass15(); var f2 = m.add2, f3 = m.add3; f2(); f3(); m.a'
        ) == '6'
Beispiel #6
0
def test_py2s_rename_function():
    code = py2js(foo1, 'bar')
    assert 'foo' not in code.lower()
    assert evaljs(code + 'bar()') == '42'
    
    code = py2js(foo1, 'xx.bar')
    assert 'foo' not in code.lower()
    assert evaljs('var xx={};\n' + code + 'xx.bar();') == '42'
Beispiel #7
0
 def test_import(self):
     with raises(JSError):
         py2js('import time')
     
     # But we do support special time funcs
     import time
     assert abs(float(evalpy('time()')) - time.time()) < 0.5
     evalpy('t0=perf_counter(); t1=perf_counter(); (t1-t0)').startswith('0.0')
Beispiel #8
0
 def test_raw_js_overloading(self):
     # more RawJS tests in test_parser3.py
     s1 = 'a=3; b=4; c=1; a + b - c'
     s2 = 'a=3; b=4; c=1; RawJS("a + b") - c'
     assert evalpy(s1) == '6'
     assert evalpy(s2) == '6'
     assert 'pyfunc' in py2js(s1)
     assert 'pyfunc' not in py2js(s2)
Beispiel #9
0
    def test_inheritance_and_super(self):
        class MyClass1:
            def __init__(self):
                self.bar = 7

            def add(self, x=1):
                self.bar += x

            def addTwo(self):
                self.bar += 2

        class MyClass2(MyClass1):
            def addTwo(self):
                super().addTwo()
                self.bar += 1  # haha, we add three!

        class MyClass3(MyClass2):
            def addTwo(self):
                super().addTwo()
                self.bar += 1  # haha, we add four!

            def addFour(self):
                super(MyClass3, self).add(4)  # Use legacy Python syntax

        code = py2js(MyClass1) + py2js(MyClass2) + py2js(MyClass3)
        code += 'var m1=new MyClass1(), m2=new MyClass2(), m3=new MyClass3();'

        # m1
        assert evaljs(code + 'm1.bar;') == '7'
        assert evaljs(code + 'm1.add();m1.bar;') == '8'
        assert evaljs(code + 'm1.addTwo();m1.bar;') == '9'
        # m2
        assert evaljs(code + 'm2.bar;') == '7'
        assert evaljs(code + 'm2.add();m2.bar;') == '8'
        assert evaljs(code + 'm2.addTwo();m2.bar;') == '10'
        # m3
        assert evaljs(code + 'm3.bar;') == '7'
        assert evaljs(code + 'm3.add();m3.bar;') == '8'
        assert evaljs(code + 'm3.addTwo();m3.bar;') == '11'
        assert evaljs(code + 'm3.addFour();m3.bar;') == '11'  # super with args

        # Inhertance m1
        assert evaljs(code + 'm1 instanceof MyClass3;') == 'false'
        assert evaljs(code + 'm1 instanceof MyClass2;') == 'false'
        assert evaljs(code + 'm1 instanceof MyClass1;') == 'true'
        assert evaljs(code + 'm1 instanceof Object;') == 'true'

        # Inhertance m2
        assert evaljs(code + 'm2 instanceof MyClass3;') == 'false'
        assert evaljs(code + 'm2 instanceof MyClass2;') == 'true'
        assert evaljs(code + 'm2 instanceof MyClass1;') == 'true'
        assert evaljs(code + 'm2 instanceof Object;') == 'true'

        # Inhertance m3
        assert evaljs(code + 'm3 instanceof MyClass3;') == 'true'
        assert evaljs(code + 'm3 instanceof MyClass2;') == 'true'
        assert evaljs(code + 'm3 instanceof MyClass1;') == 'true'
        assert evaljs(code + 'm3 instanceof Object;') == 'true'
Beispiel #10
0
def test_py2js_rename_class():
    
    code = py2js(Foo2, 'Bar')
    assert 'foo' not in code.lower()
    assert evaljs(code + 'var m=new Bar(); [m.res1(), m.res2()];') == '[ 42, 7 ]'
    
    code = py2js(Foo2, 'xx.Bar')
    assert 'foo' not in code.lower()
    assert evaljs('var xx={};\n' + code + 'var m=new xx.Bar(); [m.res1(), m.res2()];') == '[ 42, 7 ]'
Beispiel #11
0
 def test_assert(self):
     
     assert 'throw' in py2js('assert True')
     evalpy('assert true; 7') == '7'
     evalpy('assert true, "msg"; 7') == '7'
     
     catcher = 'try { %s } catch(err) { console.log(err); }'
     assert evaljs(catcher % py2js('assert false')).count('AssertionError')
     assert evaljs(catcher % py2js('assert false, "foo"')).count('foo')
Beispiel #12
0
 def test_global_vs_nonlocal(self):
     js1 = py2js('global foo;foo = 3')
     js2 = py2js('nonlocal foo;foo = 3')
     
     assert js1.meta['vars_unknown'] == set()
     assert js2.meta['vars_unknown'] == set()
     assert js1.meta['vars_global'] == set(['foo'])
     assert js2.meta['vars_global'] == set()
     
     code = """if True:
Beispiel #13
0
    def test_isinstance(self):
        # The resulting code is not particularly pretty, so we just
        # test outcome

        assert evalpy('isinstance(3.0, list) == True') == 'false'
        assert evalpy('isinstance(3.0, float) == True') == 'true'

        assert evalpy('x={}; isinstance(x.foo, "undefined")') == 'true'

        assert evalpy('isinstance(None, "null")') == 'true'
        assert evalpy('isinstance(undefined, "undefined")') == 'true'
        #
        assert evalpy('isinstance(None, "undefined")') == 'false'
        assert evalpy('isinstance(undefined, "null")') == 'false'

        assert evalpy('isinstance(3, float)') == 'true'
        assert evalpy('isinstance(3, (int, float))') == 'true'
        assert evalpy('isinstance(3, "number")') == 'true'
        #
        #assert evalpy('isinstance(3, int)') == 'false'  # int is not defined

        assert evalpy('isinstance("", str)') == 'true'
        assert evalpy('isinstance("", "string")') == 'true'
        #
        assert evalpy('isinstance("", list)') == 'false'

        assert evalpy('isinstance(True, bool)') == 'true'
        assert evalpy('isinstance(True, "boolean")') == 'true'
        #
        assert evalpy('isinstance(True, float)') == 'false'

        assert evalpy('isinstance([], list)') == 'true'
        assert evalpy('isinstance([], "array")') == 'true'
        #
        assert evalpy('isinstance([], "object")') == 'false'
        assert evalpy('isinstance([], "Object")') == 'false'
        assert evalpy('isinstance([], dict)') == 'false'

        assert evalpy('isinstance({}, dict)') == 'true'
        assert evalpy('isinstance({}, "object")') == 'true'
        #
        assert evalpy('isinstance({}, list)') == 'false'
        assert evalpy('isinstance({}, "array")') == 'false'

        assert evalpy('isinstance(eval, types.FunctionType)') == 'true'
        assert evalpy('isinstance(eval, FunctionType)') == 'true'
        assert evalpy('isinstance(3, types.FunctionType)') == 'false'

        # own class
        code = 'function MyClass () {return this;}\nvar x = new MyClass();\n'
        assert evaljs(code + py2js('isinstance(x, "object")')) == 'true'
        assert evaljs(code + py2js('isinstance(x, "Object")')) == 'true'
        assert evaljs(code + py2js('isinstance(x, "MyClass")')) == 'true'
        assert evaljs(code + py2js('isinstance(x, MyClass)')) == 'true'
Beispiel #14
0
 def test_nonlocal(self):
     assert py2js('nonlocal foo;foo = 3').strip() == 'foo = 3;'
     
     func3_code = """def func3():
         def inner():
             nonlocal x
             x = 3
         x = 2
         inner()
         return x
     """
     assert evaljs(py2js(func3_code)+'func3()') == '3'
Beispiel #15
0
def test_py2js_on_function():
    
    def foo():
        pass
    
    # normal
    jscode = py2js(foo)
    assert jscode.startswith('var foo')
    assert jscode.meta['pycode'].startswith('def foo')
    
    # renamed
    jscode = py2js(foo, 'bar')
    assert jscode.meta['pycode'].startswith('def foo')
    assert 'foo' not in jscode
    assert jscode.startswith('var bar')
    assert 'bar = function ' in jscode
    
    # renamed 2
    jscode = py2js(foo, 'bar.bla')
    assert jscode.meta['pycode'].startswith('def foo')
    assert 'foo' not in jscode
    assert not 'var bar.bla' in jscode
    assert 'bar.bla = function ' in jscode
    
    
    # Skip decorators
    stub1 = lambda x: x
    stub2 = lambda x=None: stub1
    
    @stub1
    @stub1
    def foo1():
        pass
    
    @stub2(
    )
    def foo2():
        pass
    
    @py2js
    def foo3():
        pass
    
    @py2js(indent=1)
    def foo4():
        pass
    
    assert callable(foo1)
    assert callable(foo2)
    assert py2js(foo1).meta['pycode'].startswith('def foo')
    assert py2js(foo2).meta['pycode'].startswith('def foo')
    assert foo3.startswith('var foo3')
    assert foo4.startswith('    var foo4')
 def test_async_and_await(self):
     if sys.version_info < (3, 6):
         return
     
     foo = py2js('async def foo(): return 42\n\n')
     spam = py2js('async def spam(): print(await foo())\n\n')
     eggs = py2js('async def eggs(): return await foo()\n\n')
     js = foo + spam + eggs
     
     assert 'Promise' in evaljs(js + 'foo()')
     assert 'Promise' in evaljs(js + 'spam()')
     assert 'Promise' in evaljs(js + 'eggs()')
     
     assert '42' in evaljs(js + 'spam()')
     assert '42' not in evaljs(js + 'eggs()')
Beispiel #17
0
def test_stdlib_full_and_partial():
    code = stdlib.get_full_std_lib()
    assert isinstance(code, str)
    assert 'var %shasattr =' % stdlib.FUNCTION_PREFIX in code
    assert 'var %slist =' % stdlib.FUNCTION_PREFIX in code
    assert code.count('var') > 10
    
    code = stdlib.get_partial_std_lib(['hasattr'], [], []) 
    assert isinstance(code, str)
    assert 'var %shasattr =' % stdlib.FUNCTION_PREFIX in code
    assert 'var %slist =' % stdlib.FUNCTION_PREFIX not in code
    assert code.count('var') == 1
    
    assert '_hasattr = function' in py2js('hasattr(x, "foo")')
    assert '_hasattr = function' not in py2js('hasattr(x, "foo")', inline_stdlib=False)
Beispiel #18
0
 def test_while(self):
     
     # Test code output
     line = nowhitespace(py2js('while(True): pass'))
     assert line == 'while(true){}'
     line = nowhitespace(py2js('while(not ok): pass'))
     assert 'while' in line
     
     # Test break and continue
     for9 = 'i=-1\nwhile(i<8):\n  i+=1\n  '
     assert evalpy(for9 + 'if i==4:break\n  print(i)\n0') == '0\n1\n2\n3\n0'
     assert evalpy(for9 + 'if i<6:continue\n  print(i)\n0') == '6\n7\n8\n0'
     # Test else
     assert evalpy(for9 + 'if i==3:break\nelse: print(99)\n0') == '0'
     assert evalpy(for9 + 'if i==30:break\nelse: print(99)\n0') == '99\n0'
Beispiel #19
0
    def test_overload_usage(self):

        # Can only use in a function
        with raises(JSError) as err_info:
            py2js("PSCRIPT_OVERLOAD=False\n3+4")
        assert 'PSCRIPT_OVERLOAD inside a function' in str(err_info.value)

        # Can only use with a bool
        def foo():
            PSCRIPT_OVERLOAD = 0
            return a + b

        with raises(JSError) as err_info:
            py2js(foo)
        assert 'PSCRIPT_OVERLOAD with a bool' in str(err_info.value)
Beispiel #20
0
    def test_var_args2(self):
        def func(self, foo, *args):
            return args

        code1 = py2js(func)
        #lines = [line for line in code1.split('\n') if line]

        code2 = py2js('func(0, 2, 3)')
        assert evaljs(code1 + code2, False) == '[2,3]'
        code2 = py2js('func(0)')
        assert evaljs(code1 + code2, False) == '[]'
        code2 = py2js('a=[0,2,3]\nfunc(*a)')
        assert evaljs(code1 + code2, False) == '[2,3]'
        code2 = py2js('a=[2,3]\nfunc(0,1,2,*a)')
        assert evaljs(code1 + code2, False) == '[1,2,2,3]'
Beispiel #21
0
 def test_scope(self):
     
     def func(self):
         def foo(z):
             y = 2
             stub = False  # noqa
             only_here = 1  # noqa
             return x + y + z
         x = 1
         y = 0
         y = 1  # noqa
         z = 1  # noqa
         res = foo(3)
         stub = True  # noqa
         return res + y  # should return 1+2+3+1 == 7
     
     # Find function start
     code = py2js(func)
     i = code.splitlines().index('var func;')
     assert i >= 0
     
     # Find first lines of functions, where the vars are defined
     vars1 = code.splitlines()[i+2]
     vars2 = code.splitlines()[i+4]
     assert vars1.strip().startswith('var ')
     assert vars2.strip().startswith('var ')
     
     assert 'y' in vars1 and 'y' in vars2
     assert 'stub' in vars1 and 'stub' in vars2
     assert 'only_here' in vars2 and 'only_here' not in vars1
     assert evaljs(code + 'func()') == '7'
Beispiel #22
0
def test_time2str():

    t1 = to_time_int("2018-04-24 13:18:00")
    t2 = to_time_int("2018-04-24 13:18:00Z")
    t3 = to_time_int("2018-04-24 13:18:00+0200")

    for t in (t1, t2, t2):
        assert isinstance(t, int)

    # Get outputs
    assert time2str(t1) == time2str(t1, None)
    s1 = time2str(t1, None)
    s2 = time2str(t2, 0)
    s3 = time2str(t3, 2)

    # Verify output in Python
    assert s1.startswith("2018-04-24T13:18:00")  # exact output depends on timezone
    assert s2 == "2018-04-24T13:18:00Z"
    assert s3 == "2018-04-24T13:18:00+0200"

    if not HAS_NODE:
        print("skipping tests that use node")
        return

    # Verify that JS and Python produce the same results
    js = py2js(open(dt.__file__, "rb").read().decode(), docstrings=False)
    js1 = evaljs(js + f"time2str({t1})")
    js2 = evaljs(js + f"time2str({t2}, 0)")
    js3 = evaljs(js + f"time2str({t3}, 2)")
    assert js1 == s1.rstrip("0")
    assert js2 == s2.rstrip("0")
    assert js3 == s3.rstrip("0")
Beispiel #23
0
    def test_bound_funcs_in_methods(self):
        class MyClass16:
            def foo1(self):
                self.a = 3
                f = lambda i: self.a
                return f()

            def foo2(self):
                self.a = 3

                def bar():
                    return self.a

                return bar()

            def foo3(self):
                self.a = 3

                def bar(self):
                    return self.a

                return bar()

        code = py2js(MyClass16)
        assert evaljs(code + 'var m = new MyClass16(); m.foo1()') == '3'
        assert evaljs(code + 'var m = new MyClass16(); m.foo2()') == '3'
        assert evaljs(
            code +
            'var m = new MyClass16(); try {m.foo3();} catch (err) {"ok"}'
        ) == 'ok'
Beispiel #24
0
    def test_self_becomes_this(self):
        def func(self):
            return self.foo

        code = py2js(func)
        lines = [line.strip() for line in code.split('\n') if line]
        assert 'return this.foo;' in lines
Beispiel #25
0
def py2js_tickformatter(formatter, msg=''):
    """
    Uses py2js to compile a python tick formatter to JS code
    """
    try:
        from pscript import py2js
    except ImportError:
        param.main.param.warning(
            msg+'Ensure pscript is installed ("conda install pscript" '
            'or "pip install pscript")')
        return
    try:
        jscode = py2js(formatter, 'formatter')
    except Exception as e:
        error = 'Pyscript raised an error: {0}'.format(e)
        error = error.replace('%', '%%')
        param.main.param.warning(msg+error)
        return

    args = _getargspec(formatter).args
    arg_define = 'var %s = tick;' % args[0] if args else ''
    return_js = 'return formatter();\n'
    jsfunc = '\n'.join([arg_define, jscode, return_js])
    match = re.search('(formatter \= function \(.*\))', jsfunc )
    return jsfunc[:match.start()] + 'formatter = function ()' + jsfunc[match.end():]
Beispiel #26
0
 def test_func1(self):
     code = py2js(func1)
     lines = [line for line in code.split('\n') if line]
     
     assert len(lines) == 4  # only three lines + definition
     assert lines[1] == 'func1 = function flx_func1 () {'  # no args
     assert lines[2].startswith('  ')  # indented
     assert lines[3] == '};'  # dedented
Beispiel #27
0
 def test_method1(self):
     code = py2js(self.method1)
     lines = [line for line in code.split('\n') if line]
     
     assert len(lines) == 4  # only three lines + definition
     assert lines[1] == 'method1 = function () {'  # no args, no self/this
     assert lines[2].startswith('  ')  # indented
     assert lines[3] == '};'  # dedented
Beispiel #28
0
 def test_basic_types(self):
     assert py2js('True') == 'true;'
     assert py2js('False') == 'false;'
     assert py2js('None') == 'null;'
     
     assert py2js('"bla\\"bla"') == '"bla\\"bla";'
     assert py2js('3') == '3;'
     assert py2js('3.1415') == '3.1415;'
     
     assert py2js('[1,2,3]') == '[1, 2, 3];'
     assert py2js('(1,2,3)') == '[1, 2, 3];'
     
     assert py2js('{"foo": 3, "bar": 4}') == '({foo: 3, bar: 4});'
     assert evalpy('a={"foo": 3, "bar": 4};a') == '{ foo: 3, bar: 4 }'
Beispiel #29
0
def test_dotted_unknowns():
    
    def func1():
        x = ui._layouts.SomeLayout()
        y = ui.SomeLayout.YYY
        z = ui.SomeOtherLayout
    
    js = py2js(func1)
    assert js.meta['vars_unknown'] == set(['ui._layouts.SomeLayout', 'ui.SomeLayout.YYY', 'ui.SomeOtherLayout'])
Beispiel #30
0
    def test_rawJS(self):

        code = py2js(foo)
        assert 'pyfunc' not in code
        assert '    x =' in code
        assert '    for' in code
        assert '        y +=' in code
        assert '    while' in code
        assert '        y -=' in code
Beispiel #31
0
    def __init__(self, name, store):
        if not isinstance(name, str):
            raise TypeError('JSModule needs a str name.')
        if not isinstance(store, dict):
            raise TypeError('JSModule needs a dict store.')

        # Resolve name of Python module
        py_name = name
        if name.endswith('.__init__'):
            py_name = name.rsplit('.', 1)[0]
        if py_name not in sys.modules:
            raise ValueError("Cannot find Python module coresponding to %s." % name)

        # Store module and name
        self._pymodule = sys.modules[py_name]
        self._name = get_mod_name(self._pymodule)

        # Check if name matches the kind of module
        is_package = module_is_package(self._pymodule)
        if is_package and not name.endswith('.__init__'):
            raise ValueError('Modules representing the __init__ of a package '
                             'should end with ".__init__".')
        elif not is_package and name.endswith('.__init__'):
            raise ValueError('Plain modules should not end with ".__init__".')

        # Self-register
        self._store = store
        if self.name in self._store:
            raise RuntimeError('Module %s already exists!' % self.name)
        self._store[self.name] = self

        # Bookkeeping content of the module
        self._provided_names = set()
        self._imported_names = set()
        # Stuff defined in this module (in JS)
        # We use dicts so that we can "overwrite" them in interactive mode
        self._component_classes = {}
        self._pscript_code = {}
        self._js_values = {}
        # Dependencies
        self._deps = {}  # mod_name -> [mod_as_name, *imports]
        # Caches
        self._js_cache = None
        self._css_cache = None

        if is_pscript_module(self._pymodule):
            # PScript module; transpile as a whole
            js = py2js(self._pymodule, inline_stdlib=False, docstrings=False)
            self._pscript_code['__all__'] = js
            self._provided_names.update([n for n in js.meta['vars_defined']
                                         if not n.startswith('_')])
        else:
            self._init_default_objects()
Beispiel #32
0
 def py2js(self, *args, **kwargs):
     kwargs['inline_stdlib'] = False
     kwargs['docstrings'] = False
     code = py2js(*args, **kwargs)
     return self.update(code)
Beispiel #33
0
def py2js(ctx, code):
    """transpile given Python code to JavaScript
    """
    from pscript import py2js
    print(py2js(code))
Beispiel #34
0
    def add_variable(self, name, is_global=False, _dep_stack=None):
        """ Mark the variable with the given name as used by JavaScript.
        The corresponding object must be a module, Component, class or function,
        or a json serializable value.

        If the object is defined here (or a json value) it will add JS to
        this module. Otherwise this module will import the name from
        another module.

        If ``is_global``, the name is considered global; it may be declared in
        this module, but it may also be a JS global. So we try to resolve the
        name, but do not care if it fails.
        """
        _dep_stack = _dep_stack or []
        if name in self._imported_names:
            return
        elif name in _dep_stack:
            return  # avoid dependency recursion
        elif name in ('Infinity', 'NaN'):
            return  # stubs
        elif name in self._provided_names and self.name != '__main__':
            return  # in __main__ we allow redefinitions
        if is_pscript_module(self._pymodule):
            return  # everything is transpiled and exported already
        _dep_stack.append(name)

        # Try getting value. We warn if there is no variable to match, but
        # if we do find a value we're either including it or raising an error
        try:
            val = self._pymodule
            nameparts = name.split('.')
            for i in range(len(nameparts)):
                val = getattr(val, nameparts[i])
                # Maybe we "know" (this kind of) value ...
                if isinstance(val, json_types):
                    name = '.'.join(nameparts[:i+1])
                    break
                elif isinstance(val, type) and issubclass(val, JsComponent):
                    name = '.'.join(nameparts[:i+1])
                    break
                elif val is loop and i == 0:
                    return self._add_dep_from_event_module('loop', nameparts[0])
                elif isinstance(val, (JSConstant, Asset)):
                    return  # stubs
                elif isinstance(val, logging.Logger) and i == 0:
                    # todo: hehe, we can do more here (issue #179)
                    return self._add_dep_from_event_module('logger', nameparts[0])
        except AttributeError:
            msg = 'JS in "%s" uses undefined variable %r.' % (self.filename, name)
            if is_global:
                pass  # it may be a JS-global
            elif val is self._pymodule:
                # Did not resolve first part of the name, so cannot be a JS global
                logger.warning(msg)
            else:
                raise RuntimeError(msg)  # E.g. typo in ui.Buttom
            return

        # Mark dirty
        self._changed_time = time.time()
        self._js_cache = self._css_cache = None

        if isinstance(val, types.ModuleType):
            # Modules as a whole can be converted if its a PScript module
            if is_pscript_module(val):
                self._import(val.__name__, None, None)
                self._deps[val.__name__][0] = name  # set/overwrite as-name
            else:
                t = 'JS in "%s" cannot use module %s directly unless it defines %s.'
                raise ValueError(t % (self.filename, val.__name__, '"__pscript__"'))

        elif isinstance(val, type) and issubclass(val, Component):
            if val is Component:
                return self._add_dep_from_event_module('Component')
            elif val is BaseAppComponent or val.mro()[1] is BaseAppComponent:
                # BaseAppComponent, PyComponent, JsComponent or StubComponent
                # are covered in _component2.py
                return
            elif issubclass(val, (PyComponent, JsComponent)):
                # App Component class; we know that we can get the JS for this
                if val.__jsmodule__ == self.name:
                    # Define here
                    self._provided_names.add(name)
                    self._component_classes[name] = val
                    # Recurse
                    self._collect_dependencies_from_bases(val)
                    self._collect_dependencies(val.JS.CODE, _dep_stack)
                else:
                    # Import from another module
                    self._import(val.__jsmodule__, val.__name__, name)
            else:
                # Regular Component, similar to other classes,
                # but using create_js_component_class()
                mod_name = get_mod_name(val)
                if mod_name == self.name:
                    # Define here
                    js = create_js_component_class(val, val.__name__)
                    self._provided_names.add(name)
                    self._pscript_code[name] = js
                    # Recurse
                    self._collect_dependencies_from_bases(val)
                    self._collect_dependencies(js, _dep_stack)
                else:
                    # Import from another module
                    self._import(mod_name, val.__name__, name)

        elif isinstance(val, type) and issubclass(val, bsdf.Extension):
            # A bit hacky mechanism to define BSDF extensions that also work in JS.
            # todo: can we make this better? See also app/_component2.py (issue #429)
            js = 'var %s = {name: "%s"' % (name, val.name)
            for mname in ('match', 'encode', 'decode'):
                func = getattr(val, mname + '_js')
                funccode = py2js(func, indent=1, inline_stdlib=False, docstrings=False)
                js += ',\n    ' + mname + ':' + funccode.split('=', 1)[1].rstrip(' \n;')
                self._collect_dependencies(funccode, _dep_stack)
            js += '};\n'
            js += 'serializer.add_extension(%s);\n' % name
            js = JSString(js)
            js.meta = funccode.meta
            self._pscript_code[name] = js
            self._deps.setdefault('flexx.app._clientcore',
                                 ['flexx.app._clientcore']).append('serializer')

        elif isinstance(val, pscript_types) and hasattr(val, '__module__'):
            # Looks like something we can convert using PScript
            mod_name = get_mod_name(val)
            if mod_name == self.name:
                # Define here
                try:
                    js = py2js(val, inline_stdlib=False, docstrings=False)
                except Exception as err:
                    t = 'JS in "%s" uses %r but cannot transpile it with PScript:\n%s'
                    raise ValueError(t % (self.filename, name, str(err)))
                self._provided_names.add(name)
                self._pscript_code[name] = js
                # Recurse
                if isinstance(val, type):
                    self._collect_dependencies_from_bases(val)
                self._collect_dependencies(js, _dep_stack)
            elif mod_name.endswith('.event._property'):
                return self._add_dep_from_event_module(name.split('.')[-1], name)
            else:
                # Import from another module
                self._import(mod_name, val.__name__, name)

        elif isinstance(val, RawJS):
            # Verbatim JS
            if val.__module__ == self.name:
                self._provided_names.add(name)
                self._js_values[name] = val.get_code()
            else:
                self._import(val.__module__, val.get_defined_name(name), name)

        elif isinstance(val, json_types):
            # Looks like something we can serialize
            # Unlike with RawJS, we have no way to determine where it is defined
            try:
                js = json.dumps(val)
            except Exception as err:
                t = 'JS in "%s" uses %r but cannot serialize that value:\n%s'
                raise ValueError(t % (self.filename, name, str(err)))
            self._provided_names.add(name)
            self._js_values[name] = js

        elif (getattr(val, '__module__', None) and
              is_pscript_module(sys.modules[val.__module__]) and
              val is getattr(sys.modules[val.__module__], name, 'unlikely-val')):
            # An instance from a pscript module!
            # We cannot know the "name" as its known in the module, but
            # we assume that its the same as as_name and test whether
            # it matches in the test above.
            self._import(val.__module__, name, name)

        else:
            # Cannot convert to JS
            t = 'JS in "%s" uses %r but cannot convert %s to JS.'
            raise ValueError(t % (self.filename, name, val.__class__))