Coder Social home page Coder Social logo

stefanhoelzl / vue.py Goto Github PK

View Code? Open in Web Editor NEW
307.0 18.0 20.0 2.49 MB

Pythonic Vue.js

Home Page: https://stefanhoelzl.github.io/vue.py/

License: MIT License

Makefile 0.98% HTML 0.44% Python 98.59%
python web reactive frontend framework client-side vuejs vue ui gui

vue.py's Introduction

vue.py

Build Status PyPI License

use Vue.js with pure Python

vue.py provides Python bindings for Vue.js. It uses brython to run Python in the browser.

Here is a simple example of an vue.py component

from browser import alert
from vue import VueComponent

class HelloVuePy(VueComponent):
    greeting = "Hello vue.py"

    def greet(self, event):
        alert(self.greeting)

    template = """
    <button @click="greet">click me</button>
    """

HelloVuePy("#app")

Installation

$ pip install vuepy

Development Status

The goal is to provide a solution to write fully-featured Vue applications in pure Python.

To get an overview what currently is supported, have a look at the Documentation.

Have a look here to see whats planned!

See also the Limitations

Documentation

Documentation for the last release is available here.

Documentation fo the current master branch can be found here.

Examples can be found here. These are vue.py versions of the Vue.js examples

Performance

Initial loading times of vue.py apps can be very long. Especially when loading a lot of python files. Still figuring out how to solve this.

Have not done any peformance tests, but havent noticed any issues with performance as soon as the app was fully loaded.

Development

Getting Started

Open in gitpod.io

Get the code

$ git clone https://github.com/stefanhoelzl/vue.py.git
$ cd vue.py

Optionally you can create a venv

$ python -m venv venv
$ source venv/bin/activate

Install required python packages, the chromedriver for selenium and brython

$ make env.up

Format the code

$ make format

Run tests

$ make tests           # runs all tets
$ make tests.unit      # runs unit tests
$ make tests.selenium  # runs selenium tests
$ make tests.cli       # runs cli tests
$ make tests TEST=cli/test_provider.py::TestRenderIndex::test_defaults # run explicit test

Run an example

$ make run APP=examples/tree_view  # makes example available on port 5000

Reset your development environment (clean up, reinstall packages and redownload needed files)

$ make env.down
$ make env.up

Publish a new release

$ release release-candidate

Contributing

see CONTRIBUTING

License

This project is licensed under the MIT License - see the LICENSE file for details

vue.py's People

Contributors

aaronchn avatar meteozond avatar stefanhoelzl avatar vadolasi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue.py's Issues

vuepy.yml in component foder is not included

Not sure if this is an intended or a missing feature, but given the followins structure:

- app.py
- index.html
- some_style.css
- vuepy.yml
- component_x
    - component_x.py
    - component_x.html
    - css
        - first.css
        - second.css  
    - vuepy.yml

testing component_x separately works fine but when including it in app.py, I need to explicitly copy the content of component_x/vuepy.yml into the main vuepy.yml to get it to work. I.e., in top-level vuepy.yml, I need to have the following:

templates:
  index: index.html
  componentx: component_x/component_x.html
stylesheets:
  - some_style.css
  - component_x/css/first.css
  - component_x/css/second.css

is there a way to avoid manually copying the content of component_x/yuepy.yml in the main vuepy.yml?

Thank you,
M

Containers in VueX are Javascript objects

When working with VueStore, complex objects (lists, dicts) are converted to Javascript types and are not workable as python types.

eg

from vue import VueComponent, VueStore, computed

class Store(VueStore):
    data = {
        'a': 123,
        'b': 456,
    }

class DataComponent(VueComponent):
    id: str
    template = '''
        <div
            :id="id">
            {{ data }}
        </div>
    '''
    @computed
    def data(self):
        return self.store.data[self.id]

class App(VueComponent):
    template = '''
        <div>
            <data-component
                v-for="id in ids">
            </data-component>
        </div>
    '''

    @computed
    def ids(self):
        print(f'self.store.data = {self.store.data}')
        return self.store.data.keys()


App("#app", store=Store())

html

<body>
    <div id="app"></div>
</body>

I get the following output:

self.store.data = <Javascript Object object: [object Object]> 

Traceback (most recent call last):
  File http://127.0.0.1:5000/#__main__ line 1, in <module>
    import test
  File /static/test/__init__.py line 1, in <module>
    from . import app
  File /static/test/app.py line 42, in <module>
    App("#app", store=Store())
  File /static/vue/vue.py line 70, in __new__
    return Object.from_js(window.Vue.new(Object.to_js(init_dict)))
  File /static/vue/decorators/base.py line 32, in ids
    return Object.to_js(fn(*args, **kwargs))
  File /static/test/app.py line 30, in ids
    return self.store.data.keys()
brython.min.js:7 AttributeError: keys

I get similar issues with @getter and @mutate methods defined inside the store.

Incomplete installation instructions

According to the installation instructions, all the user has to do is pip install this project. This is not exactly true, because there is an implicit vue.js (and hence node) requirement. What makes things worse is that it only becomes apparent when the user checks why vue-cli deploy throws an exception (it would be nice if the exception was replaced with a simple error message saying the vue.js must be installed).

Also, it would be nice if it was in the description how vue-cli finds the main entry point of the application or how it can be pointed to a custom Python file.

Support .vue single file components

The spec for reference.

import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'

I think an implementation of this exact API would involve monkey patching the import statement to load .vue files. That seems like maybe not the best idea, and an sfg loader utility/class would be required underneath regardless. That could have a more explicit API.

front-end and back-end confusion

I'm trying to implement this exercise based on vue.py,

But I encountered a big confusion, in the above exercise, the server side is played by flask and continuously listens and accepts address requests (/ping) from the client (vue) and gives a response.

@app.route('/ping', methods=['GET'])
def ping_pong():
    return jsonify('pong!')

Based on my understanding of vue.py I found that the server side is still played by flask, but does not explicitly respond to an address request. In other words, the clear distinction between the front and back end is missing.

If possible, could you rewrite the ping->pong example in the same way as vue.py?
I know this will waste your valuable time, but I think this issue may be more important and some newbies are easily confused like this.

Thanks!

Vuex + javascript component

Hi,

I created some component in JS + ES6 + Nodejs + ... linked with Vuex.

I imported my lib, Instanced Vuex from vuepy. It does not work the error is the $store object is dict wrapped not an js object.

have you any solution ?

VueComponent.__new__ method should take any instance of component. not only store

Actually we have got

def __new__(cls, el, store=None, **data):
        init_dict = cls.init_dict()
        init_dict.update(el=el)
        init_dict.update(propsData=data)
        if store:
            init_dict.update(store=store)
        return Object.from_js(window.Vue.new(init_dict))

For my project I need vue-router. Really easy to import in vuepy.yml

scripts:
    - https://unpkg.com/[email protected]/dist/vue-router.js

Easy to import in app.py

VueRouter = js_lib("VueRouter")
Vue.use(VueRouter)
router = VueRouter.new(dict(routes=[
    {'name': 'cp1', 'path': '/cp1', 'component': {'template': '<cp1 />'}},
    {'name': 'cp2', 'path': '/cp2', 'component': {'template': '<cp2 />'}},
]))

But it is doesnt work when I do an instance of my application

App("#app", router=router)

The only way is actualy to overwrite VueComponent.

class VueComponent2(VueComponent):

    def __new__(cls, el, store=None, router=None, **data):
        init_dict = cls.init_dict()
        init_dict.update(el=el)
        init_dict.update(propsData=data)
        if store:
            init_dict.update(store=store)
        if router:
            init_dict.update(router=router)
        return Object.from_js(window.Vue.new(init_dict))


class App(VueComponent2):

or overwrite the classmethod init_dict

class App(VueComponent):

    @classmethod
    def init_dict(cls):
        init_dict = super(App, cls).init_dict()
        init_dict.update(router=router)
        return init_dict

    template = "<router-view></router-view>"


App("#app")

For me it is not the good solution. I propose two other solutions

  1. easiest to implement
def __new__(cls, el, **kwargs):
        init_dict = cls.init_dict()
        init_dict.update(el=el)
        propsData = kwargs.pop('propsData', {})
        init_dict.update(propsData=propsData)
        init_dict.update(**kwargs)  # store, router, i18n or what ever
        return Object.from_js(window.Vue.new(init_dict))
  1. Add a new Attribute on the component (only for the app)
def __new__(cls, el, **data):
        init_dict = cls.init_dict()
        init_dict.update(el=el)
        init_dict.update(propsData=data)
        behaviour = getattr(cls, 'behaviour', {})
        if behaviour:
                init_dict.update(**behaviour)
        return Object.from_js(window.Vue.new(init_dict))

class App(VueComponent):
        behaviour = {
               'store': store,
               'router': router,
               ...
        }

store.commit causes errors

When using the "store.commit" method, I get an error before the getter function is called.
This is preventing me from having complex setters in the store.

Example app to demonstrate

from vue import VueComponent, VueStore, mutation

class Store(VueStore):
    test_value = 1

    @mutation
    def increment_test_value(self, value):
        print('increment')
        self.test_value += value


class App(VueComponent):
    template = '''
        <div>
            <button @click="set_value">{{ value }}</button>
        </div>
    '''
    def set_value(self, event):
        self.store.commit('increment_test_value', 1)

    @computed
    def value(self):
        return self.store.test_value

App("#app", store=Store())

html

<body>
    <div id="app"></div>
</body>

Output:

Error
    at Object._b_.AttributeError.$factory (eval at $make_exc (brython.min.js:7), <anonymous>:1:2566)
    at $B.JSObj.__getattribute__ (brython.min.js:7)
    at Object.$B.$getattr (brython.min.js:7)
    at wrapper275 (eval at run_py (brython.min.js:7), <anonymous>:165:296)
    at s.wrapper63 (eval at run_py (brython.min.js:7), <anonymous>:308:185)
    at s.<anonymous> (brython.min.js:7)
    at vuex.min.js:6
    at vuex.min.js:6
    at Array.forEach (<anonymous>)
    at vuex.min.js:6
brython.min.js:7 Traceback (most recent call last):
  File /static/vue/decorators/base.py line 32, in set_value
    return Object.to_js(fn(*args, **kwargs))
  File /static/test/app.py line 21, in set_value
    self.store.commit('increment_test_value', 1)
  File /static/vue/bridge/vuex_instance.py line 42, in commit
    self.__commit__(mutation_name, {"args": args, "kwargs": kwargs})
  File /static/vue/decorators/base.py line 32, in wrapper
    return Object.to_js(fn(*args, **kwargs))
  File /static/vue/decorators/mutation.py line 19, in wrapper
    )
brython.min.js:7 AttributeError: get
brython.min.js:7 error Error
    at Object._b_.AttributeError.$factory (eval at $make_exc (brython.min.js:7), <anonymous>:1:2566)
    at $B.JSObj.__getattribute__ (brython.min.js:7)
    at Object.$B.$getattr (brython.min.js:7)
    at wrapper275 (eval at run_py (brython.min.js:7), <anonymous>:165:296)
    at s.wrapper63 (eval at run_py (brython.min.js:7), <anonymous>:308:185)
    at s.<anonymous> (brython.min.js:7)
    at vuex.min.js:6
    at vuex.min.js:6
    at Array.forEach (<anonymous>)
    at vuex.min.js:6
brython.min.js:7 attribute commit of self s {_committing: true, _actions: {…}, _actionSubscribers: Array(0), _mutations: {…}, _wrappedGetters: {…}, …} ƒ (t,e,n){return u.call(i,t,e,n)} (2) ['increment_test_value', {…}] Arguments(2) ['increment_test_value', {…}, callee: ƒ, Symbol(Symbol.iterator): ƒ]
brython.min.js:7 Error
    at Object._b_.AttributeError.$factory (eval at $make_exc (brython.min.js:7), <anonymous>:1:2566)
    at $B.JSObj.__getattribute__ (brython.min.js:7)
    at Object.$B.$getattr (brython.min.js:7)
    at wrapper275 (eval at run_py (brython.min.js:7), <anonymous>:165:296)
    at s.wrapper63 (eval at run_py (brython.min.js:7), <anonymous>:308:185)
    at s.<anonymous> (brython.min.js:7)
    at vuex.min.js:6
    at vuex.min.js:6
    at Array.forEach (<anonymous>)
    at vuex.min.js:6
brython.min.js:7 Traceback (most recent call last):
  File /static/vue/decorators/base.py line 32, in set_value
    return Object.to_js(fn(*args, **kwargs))
  File /static/test/app.py line 21, in set_value
    self.store.commit('increment_test_value', 1)
  File /static/vue/bridge/vuex_instance.py line 42, in commit
    self.__commit__(mutation_name, {"args": args, "kwargs": kwargs})
  File /static/vue/decorators/base.py line 32, in wrapper
    return Object.to_js(fn(*args, **kwargs))
  File /static/vue/decorators/mutation.py line 19, in wrapper
    )
brython.min.js:7 AttributeError: get
vue.min.js:6 Error
    at Object._b_.AttributeError.$factory (eval at $make_exc (brython.min.js:7), <anonymous>:1:2566)
    at $B.JSObj.__getattribute__ (brython.min.js:7)
    at Object.$B.$getattr (brython.min.js:7)
    at wrapper275 (eval at run_py (brython.min.js:7), <anonymous>:165:296)
    at s.wrapper63 (eval at run_py (brython.min.js:7), <anonymous>:308:185)
    at s.<anonymous> (brython.min.js:7)
    at vuex.min.js:6
    at vuex.min.js:6
    at Array.forEach (<anonymous>)
    at vuex.min.js:6

Looks like MRO is unusable

from vue import *


class Parent(VueComponent):
    @computed
    def my_computed(self):
        return 'Parent'

    template = '<div>Hello {{my_computed}}!</div>'


class Child(Parent):
    @computed
    def my_computed(self):
        return f'Child of {super().my_computed()}'


Child('#app')
Javascript exception: TypeError: Cannot read properties of undefined (reading '__mro__')
    at $$super.__getattribute__ (vuepy.js:7406:73)
    at $B.$getattr (vuepy.js:6953:13)
    at my_computed1 (eval at run_py (vuepy.js:9261:14), <anonymous>:160:83)
    at Vue.wrapper63 (eval at run_py (vuepy.js:9261:14), <anonymous>:360:185)
    at Vue.<anonymous> (vuepy.js:9027:26)
    at Watcher.get (vue.js:4478:27)
    at Watcher.evaluate (vue.js:4583:23)
    at Proxy.computedGetter (vue.js:4832:19)
    at Proxy.eval (eval at createFunction (vue.js:11649:14), <anonymous>:3:44)
    at Vue._render (vue.js:3551:24)
vuepy.js:7875 Array(5)0: "app_Child_4_my_computed_5"1: {self: {…}, $line_info: '15,app', $f_trace: {…}, __annotations__: {…}, $parent: undefined, …}2: "app"3: {__class__: {…}, __name__: 'app', __doc__: {…}, __package__: '', __loader__: {…}, …}4: ƒ my_computed1(self)length: 5[[Prototype]]: Array(0)
vuepy.js:7908 test is js exc is recursion error TypeError: Cannot read properties of undefined (reading '__mro__')
    at $$super.__getattribute__ (vuepy.js:7406:73)
    at $B.$getattr (vuepy.js:6953:13)
    at my_computed1 (eval at run_py (vuepy.js:9261:14), <anonymous>:160:83)
    at Vue.wrapper63 (eval at run_py (vuepy.js:9261:14), <anonymous>:360:185)
    at Vue.<anonymous> (vuepy.js:9027:26)
    at Watcher.get (vue.js:4478:27)
    at Watcher.evaluate (vue.js:4583:23)
    at Proxy.computedGetter (vue.js:4832:19)
    at Proxy.eval (eval at createFunction (vue.js:11649:14), <anonymous>:3:44)
    at Vue._render (vue.js:3551:24) TypeError: Cannot read properties of undefined (reading '__mro__')
vuepy.js:7876 recursion error ? false
vuepy.js:7908 test is js exc is recursion error TypeError: Cannot read properties of undefined (reading '__mro__')
    at $$super.__getattribute__ (vuepy.js:7406:73)
    at $B.$getattr (vuepy.js:6953:13)
    at my_computed1 (eval at run_py (vuepy.js:9261:14), <anonymous>:160:83)
    at Vue.wrapper63 (eval at run_py (vuepy.js:9261:14), <anonymous>:360:185)
    at Vue.<anonymous> (vuepy.js:9027:26)
    at Watcher.get (vue.js:4478:27)
    at Watcher.evaluate (vue.js:4583:23)
    at Proxy.computedGetter (vue.js:4832:19)
    at Proxy.eval (eval at createFunction (vue.js:11649:14), <anonymous>:3:44)
    at Vue._render (vue.js:3551:24) TypeError: Cannot read properties of undefined (reading '__mro__')
vuepy.js:7874 Javascript exception: TypeError: Cannot read properties of undefined (reading '__mro__')
    at $$super.__getattribute__ (vuepy.js:7406:73)
    at $B.$getattr (vuepy.js:6953:13)
    at my_computed1 (eval at run_py (vuepy.js:9261:14), <anonymous>:160:83)
    at Vue.wrapper63 (eval at run_py (vuepy.js:9261:14), <anonymous>:360:185)
    at Vue.<anonymous> (vuepy.js:9027:26)
    at Watcher.get (vue.js:4478:27)
    at Watcher.evaluate (vue.js:4583:23)
    at Proxy.computedGetter (vue.js:4832:19)
    at Proxy.eval (eval at createFunction (vue.js:11649:14), <anonymous>:3:44)
    at Vue._render (vue.js:3551:24)
vuepy.js:7875 Array(5)
vuepy.js:7908 test is js exc is recursion error TypeError: Cannot read properties of undefined (reading '__mro__')
    at $$super.__getattribute__ (vuepy.js:7406:73)
    at $B.$getattr (vuepy.js:6953:13)
    at my_computed1 (eval at run_py (vuepy.js:9261:14), <anonymous>:160:83)
    at Vue.wrapper63 (eval at run_py (vuepy.js:9261:14), <anonymous>:360:185)
    at Vue.<anonymous> (vuepy.js:9027:26)
    at Watcher.get (vue.js:4478:27)
    at Watcher.evaluate (vue.js:4583:23)
    at Proxy.computedGetter (vue.js:4832:19)
    at Proxy.eval (eval at createFunction (vue.js:11649:14), <anonymous>:3:44)
    at Vue._render (vue.js:3551:24) TypeError: Cannot read properties of undefined (reading '__mro__')
vuepy.js:7876 recursion error ? false
vuepy.js:7908 test is js exc is recursion error TypeError: Cannot read properties of undefined (reading '__mro__')
    at $$super.__getattribute__ (vuepy.js:7406:73)
    at $B.$getattr (vuepy.js:6953:13)
    at my_computed1 (eval at run_py (vuepy.js:9261:14), <anonymous>:160:83)
    at Vue.wrapper63 (eval at run_py (vuepy.js:9261:14), <anonymous>:360:185)
    at Vue.<anonymous> (vuepy.js:9027:26)
    at Watcher.get (vue.js:4478:27)
    at Watcher.evaluate (vue.js:4583:23)
    at Proxy.computedGetter (vue.js:4832:19)
    at Proxy.eval (eval at createFunction (vue.js:11649:14), <anonymous>:3:44)
    at Vue._render (vue.js:3551:24) TypeError: Cannot read properties of undefined (reading '__mro__')
vuepy.js:9027 TypeError: Cannot read properties of undefined (reading '__mro__')
    at $$super.__getattribute__ (vuepy.js:7406:73)
    at $B.$getattr (vuepy.js:6953:13)
    at my_computed1 (eval at run_py (vuepy.js:9261:14), <anonymous>:160:83)
    at Vue.wrapper63 (eval at run_py (vuepy.js:9261:14), <anonymous>:360:185)
    at Vue.<anonymous> (vuepy.js:9027:26)
    at Watcher.get (vue.js:4478:27)
    at Watcher.evaluate (vue.js:4583:23)
    at Proxy.computedGetter (vue.js:4832:19)
    at Proxy.eval (eval at createFunction (vue.js:11649:14), <anonymous>:3:44)
    at Vue._render (vue.js:3551:24)
vue.js:634 [Vue warn]: Error in render: "Error"

(found in <Root>)
warn @ vue.js:634
vue.js:1897 Error
    at _b_.AttributeError.$factory (eval at $make_exc (vuepy.js:7929:5), <anonymous>:41:354)
    at $B.$getattr (vuepy.js:6884:26)
    at Object.getattr (vuepy.js:6848:11)
    at Vue.<anonymous> (vuepy.js:9028:17)
    at Watcher.get (vue.js:4478:27)
    at Watcher.evaluate (vue.js:4583:23)
    at Proxy.computedGetter (vue.js:4832:19)
    at Proxy.eval (eval at createFunction (vue.js:11649:14), <anonymous>:3:44)
    at Vue._render (vue.js:3551:24)
    at Vue.updateComponent (vue.js:4067:23)
logError @ vue.js:1897

deploy with flask shows error

Steps

  • install vuepy and flask
  • create app.py with example code
  • run vuecli deploy flask
  • open served page

Expected

Spinner disappears, shows example app

Actual

Spinner stays, error on consoleModuleNotFoundError: vue

Extras

The setup works for the static deployment.

Build target as web component

Is it possible to build a web-component from a VueComponent Class? Vue.js can do that using

vue build --target wc <component-name>

and Brython supports web components (https://brython.info/static_doc/en/webcomponent.html) but has a different way of implementing them.

I can't figure out how to do with Vuepy's.

For example:

#test_component.py
from vue import VueComponent

class TestComponent(VueComponent):
    template = "<p>This is a simple component</p>"

TestComponent.register("test-component")

How can I use the above as a modular web component in a static Brython project?

<body onLoadd="brython()">
<test-component></test-component>


</body>

Thanks!

How to do a simple ajax request

This shouldn't be strictly an issue, it may just be a case of what I already know not being enough to implement an idea. Nonetheless, I would still like to ask for some help here, and if my request is not considered rude and excessive, I will PR to the project as much as possible once I have made some progress and learned something.

/app.py

import os, sys
root_path = os.path.abspath(os.path.join(".."))
sys.path.append(root_path)

from vue import VueComponent, VueRouter, VueRoute
from components.comm import Foo, Bar, Ping

class Router(VueRouter):
    routes = [
        VueRoute("/foo", Foo),
        VueRoute("/bar", Bar),
        VueRoute("/ping", Ping)
    ]

class App(VueComponent):
    components = [
        Ping,
    ]

    template = """
        <div>
            <p>
                <router-link to="/foo">Go to Foo</router-link>
                <router-link to="/bar">Go to Bar</router-link>
                <router-link to="/ping">Go to Ping</router-link>
            </p>
            <router-view></router-view>
        </div>
    """

App("#app" , router=Router())

/components/comm.py

from vue import VueComponent
from browser import ajax, alert, console

class Foo(VueComponent):
    template = "<div>foo</div>"

class Bar(VueComponent):
    msg = "Hello!"
    template = "<div><p>{{msg}}</p></div>"
    
class Ping(VueComponent):
    
    template = """
    <div>
        <button @click="greet">To greet</button>
        <button @click="doAjax">Get current time</button>
        <div><p>{{current_time}}</p></div>
    </div>
    """
    greeting = "Hello vue.py"
    current_time = ""
    url = "http://worldtimeapi.org/api/timezone/America/Los_Angeles"

    def greet(self, event):
        alert(self.greeting) 


    def doAjax(self,req):
        self.req = ajax.get(self.url, oncomplete=self.read, mode="text")
        console.log(self.req.status)

    def read(self, req):
        self.current_time = self.req.text

when click the "Get current time" button:

ajax

support for custom router implementations

@vadolasi made in #12 the proposal to support custom vue router implementations.
An example how to use such a implementation with vue.js is shown here

parameter proposal

The initial proposal looks like this

class VueRouter(Wrapper):
    @classmethod
    def init_dict(cls):
        return VueRouterFactory.get_item(cls)

    def __new__(cls, vue_router_class=window.VueRouter):
        return vue_router_class.new(cls.init_dict())

using this would look like this

class Router(VueRouter):
    routes = []

App("#app", router=Router(vue_router_class=window.CustomRouter))

class attribute proposal

another proposal could look like this

class VueRouter(Wrapper):
    RouterClass = window.VueRouter

    @classmethod
    def init_dict(cls):
        return VueRouterFactory.get_item(cls)

    def __new__(cls):
        return RouterClass.new(cls.init_dict())

using this would look like this

class Router(VueRouter):
    RouterClass = window.CustomRouter
    routes = []

App("#app", router=Router())

The advantage of the class attribute proposal would be that the definition of the custom implementation and the declaration of the actual Router class is together.
This means by looking at the Router implementation it can be understood completely.
And it is also closer to the definition of other vue.py objects, where most of the functionality is described by class attributes/methods.

In the other proposal to understand the whole Router implementation someone also has to look at the App initialization.

So I would propose to implement the class attribute proposal.
@vadolasi does this work for your use case?

loading indicator only

hello i tried your sample code but all i get is a loading indicator.
Also errors in the vue-cli deploy live
image

Exceptions when accessing undefined values in Bridged Dicts

I'm trying to implement functionality in the Router beyond just the routes property.

Specifically, the beforeEach function.

Using the router example from the documentation, I modify it like so:

router = Router()

def before_each(to_, from_, next):
    print(f'before_each({to_}, {from_}, {next})')
    print(f'type(to_) = {type(to_)}')
    print(f'type(from_) = {type(from_)}')
    print(f'to_.keys() = {to_.keys()}')
    print(f'to_.values() = {to_.values()}')
    print(f'to_.items() = {to_.items()}')
    next()

router.beforeEach(pyjs_bridge(before_each))

The output of this is:

before_each([object Window], [object Window], <function >)

brython.min.js:1 type(to_) = <class 'vue.bridge.dict.Dict'>

brython.min.js:1 type(from_) = <class 'vue.bridge.dict.Dict'>

brython.min.js:1 to_.keys() = ('name', 'meta', 'path', 'hash', 'query', 'params', 'fullPath', 'matched')

vue-router.js:22 [vue-router] uncaught error during route navigation:

vue-router.js:2322 name
    at Object._b_.AttributeError.$factory (eval at $B.$make_exc (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:327985), <anonymous>:3:15)
    at Object.$B.attr_error (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:330533)
    at $B.JSObj.__getattribute__ (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:402240)
    at Object.$B.$getattr (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:273895)
    at getattr (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:267994)
    at __getitem__497 (eval at run_py (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:414511), <anonymous>:251:99)
    at Object.$B.$getitem (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:221124)
    at eval (eval at run_py (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:414511), <anonymous>:878:11)
    at Generator.next (<anonymous>)
    at Object.$B.generator.send (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:643756)

vue-router.js:2286 Uncaught (in promise) name
    at Object._b_.AttributeError.$factory (eval at $B.$make_exc (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:327985), <anonymous>:3:15)
    at Object.$B.attr_error (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:330533)
    at $B.JSObj.__getattribute__ (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:402240)
    at Object.$B.$getattr (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:273895)
    at getattr (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:267994)
    at __getitem__497 (eval at run_py (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:414511), <anonymous>:251:99)
    at Object.$B.$getitem (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:221124)
    at eval (eval at run_py (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:414511), <anonymous>:878:11)
    at Generator.next (<anonymous>)
    at Object.$B.generator.send (https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js:1:643756)

As you can see, any attempt to access the values (it seems to be specifically the 'name' value in this case) causes issues.

However, I am able to get out the values the VueRoute actually defined.
Ie. using:

    print(f'to_["path"] = {to_["path"]}')
    print(f'to_.get("component") = {to_.get("component")}')

Doesn't cause an exception and does lead to output

to_["path"] = /page1

to_.get("component") = None

drop the dependencies with flask

Hi, you made an incredible library.

my issue came from, i am pyramid user, and i don't want any dependencies with flask.

For me, a better pattern would be to use the extras_require to install web application dependencies.

The Provider class should verify if the dependencies are satified to be used

  • pip install vuepy[flask]: add flask dependencies
  • pip install vuepy[pyramid]: add pyramid dependencies
  • pip install vuepy[django]: add django dependencies
  • pip install vuepy[bottle]: add bottle dependencies
  • pip install vuepy: No dependencies is added, only the Static provider can be called

I hope, my issue is understanding.

Vue-SocketIO callback issues

The example from #24 demonstrates a console log I'm seeing from Brython, "empty stack".

This seems innocuous in this case (as the callback's "self" parameter is well-formed).

But I'm also seeing it when using vue-socketio, and when using it there. Not only that, but callbacks don't seem to have a "self".

I've tried to make a minimal example below, but appreciate that setting up websockets is a bit non-standard.

This example also demonstrate's vue-socketio's inability to call the mutation functions in the Store object.
I wrote a JS equivalent of this which exhibited no issues, so it's clearly the py<->js interop.

server.py

import os
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from starlette.responses import FileResponse
import socketio

def relative_dir(path):
    return os.path.join(os.path.dirname(__file__), path)

app = FastAPI()

app.sio = socketio.AsyncServer(async_mode='asgi')
app.mount('/ws', socketio.ASGIApp(app.sio))

app.mount("/static", StaticFiles(directory=relative_dir('static')), name="static")

@app.get("/")
async def read_index():
    return FileResponse(relative_dir('static/index.html'))

@app.sio.event()
def connect(sid, *args, **kwargs):
    print(f'{sid} connected')

@app.sio.event()
def disconnect(sid, *args, **kwargs):
    print(f'{sid} disconnected')

if __name__ == '__main__':
    import uvicorn
    uvicorn.run("basic_server:app", host="127.0.0.1", port=5000, log_level="info")

index.html

<html>
<head>
    <title>TEST</title>
</head>
<body onload="brython({cache: true, pythonpath: ['/static']})">
    <div id="app"></div>
    <!-- socketio -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/client-dist/socket.io.min.js"></script>
    <!-- vue -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuex.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue-router.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue-socketio.min.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/brython_stdlib.min.js"></script>

    <script type="text/python">
        from textwrap import dedent
        from browser import window, document, load, html
        from vue import Vue, VueStore, VueComponent, data, computed, mutation
        from vue.decorators.base import VueDecorator, pyjs_bridge

        class Sockets(VueDecorator):
            __key__ = "sockets"
            def __init__(self, fn, name=None):
                self.__id__ = name or fn.__name__
                self.__value__ = pyjs_bridge(fn)

        def sockets(fn):
            if callable(fn):
                return Sockets(fn)
            name = fn
            def inner(fn):
                return Sockets(fn, name)
            return inner

        class Store(VueStore):
            @mutation
            def socket_connect(self):
                print(f'Store.socket_connect()')
            @mutation
            def socket_set_username(self, username):
                print(f'Store.socket_set_username({username})')

        class App(VueComponent):
            template = '<div>Hello</div>'

            @sockets
            def connect(self, *args, **kwargs):
                print(f'App.connect({self}, {args}, {kwargs})')

        store_ = Store()

        Vue.use(window.VueSocketIO.new({
            'debug': True,
            'connection': window.io({
                'path': '/ws/socket.io',
                'transports': ["websocket"],
            }),
            'vuex': {
                'store': store_,
                'actionPrefix': 'socket_',
                'mutationPrefix': 'socket_'
            },
        }))

        App("#app", store=store_)
    </script>
</body>
</html>

Browser console output:

Vue-Socket.io: Received socket.io-client instance 
Vue-Socket.io: Vuex adapter enabled 
Vue-Socket.io: Vuex socket mutations enabled 
Vue-Socket.io: Vuex socket actions enabled 
Vue-Socket.io: Vue-Socket.io plugin enabled 
Vue-Socket.io: #connect subscribe, component: undefined 
vue.min.js:6 Error: callback must be a function
    at t.value (vue-socketio.min.js:14:12327)
    at vue-socketio.min.js:14:9569
    at Array.forEach (<anonymous>)
    at Cn.mounted (vue-socketio.min.js:14:9495)
    at Be (vue.min.js:6:11407)
    at Qt (vue.min.js:6:25438)
    at vue.min.js:6:68707
    at Cn.$mount (vue.min.js:6:68726)
    at Cn.$mount (vue.min.js:6:94030)
    at Cn.t._init (vue.min.js:6:33111)

Vue-Socket.io: Broadcasting: #connect, Data: 
empty stack
App.connect(None, (), {})

There are a few things here:

  1. The "callback must be a function" error.
    Which is being triggered here in vue-socketio.

  2. The callback in App prints 'None' for its value of 'self'

  3. The "empty stack" warning from Brython when using callbacks.

I appreciate vue-socketio isn't your library, but I'm not sure where else to go for assistance.
I've tried poking around inside the vue.py, but I simply don't understand most of what it is attempting to do.

Child component of the router does not support data

Error:

from vue import VueComponent, VueRouter, VueRoute

class Foo(VueComponent):
    template = "<div>{{ text }}</div>"
    text = "foo"

class Router(VueRouter):
    routes = [
        VueRoute("/foo", Foo),
    ]

class App(VueComponent):
    template = """
        <div>
            <router-view></router-view>
        </div>
    """

App("#app", router=Router())

Ok:

class Foo(VueComponent):
    template = "<div>{{ text }}</div>"
    text = "foo"

class FooRoot(VueComponent):
    template = "<Foo />"

class Router(VueRouter):
    routes = [
        VueRoute("/foo", FooRoot),
    ]

i am getting error while running vue-cli deploy flask

info

root@miop-HP-Convertible-x360-11-ab1XX:/home/miop/belajar/reactpy-router# python3 --version
Python 3.10.6
    from .environment import Environment
  File "/usr/local/lib/python3.10/dist-packages/jinja2/environment.py", line 25, in <module>
    from .defaults import BLOCK_END_STRING
  File "/usr/local/lib/python3.10/dist-packages/jinja2/defaults.py", line 3, in <module>
    from .filters import FILTERS as DEFAULT_FILTERS  # noqa: F401
  File "/usr/local/lib/python3.10/dist-packages/jinja2/filters.py", line 13, in <module>
    from markupsafe import soft_unicode
ImportError: cannot import name 'soft_unicode' from 'markupsafe' (/usr/local/lib/python3.10/dist-packages/markupsafe/__init__.py)

mycode

from vue import *

class App(VueComponent):
    template = "<div>Hello vue.py</div>"
App("#app")

How to correctly specify the --src parameter

Hi

My project structure is.

root
  |
  |---backend
  |    |----backend.py
  |
  |--client
  |    |----app.py

I tried to execute the deploy command in the root directory and the result is as follows.
Screenshot_2022-04-29_20-57-41

Is my intent reasonable? If my intention is appropriate, please check if the --src parameter is correctly fetched by vue.py.

Thanks!

flask not launching

Installation

pip install vuepy
pip install vuepy[flask]
mkdir vuepy
cd vuepy

App.py :


from vue import *

class App(VueComponent):
    template = "<div>Hello vue.py</div>"
App("#app")

vue-cli deploy flask

here is the server results:

  • Serving Flask app "vuecli.provider.flask" (lazy loading)
  • Environment: production
    WARNING: This is a development server. Do not use it in a production deployment.
    Use a production WSGI server instead.
  • Debug mode: off
  • Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
    127.0.0.1 - - [18/Nov/2021 11:24:23] "GET / HTTP/1.1" 200 -
    127.0.0.1 - - [18/Nov/2021 11:24:23] "GET /vuepy.js HTTP/1.1" 200 -
    127.0.0.1 - - [18/Nov/2021 11:24:23] "GET /vue.js HTTP/1.1" 200 -
    127.0.0.1 - - [18/Nov/2021 11:24:23] "GET /loading.gif HTTP/1.1" 200 -
    127.0.0.1 - - [18/Nov/2021 11:24:23] "GET /favicon.ico HTTP/1.1" 404 -
    127.0.0.1 - - [18/Nov/2021 11:24:23] "GET /entry_point.py?1637231063646 HTTP/1.1" 200 -
    127.0.0.1 - - [18/Nov/2021 11:24:23] "GET /app.py?v=1637231063662 HTTP/1.1" 404 -
    127.0.0.1 - - [18/Nov/2021 11:24:23] "GET /app/init.py?v=1637231063668 HTTP/1.1" 404 -
    127.0.0.1 - - [18/Nov/2021 11:24:23] "GET /Lib/site-packages/app.py?v=1637231063680 HTTP/1.1" 404 -
    127.0.0.1 - - [18/Nov/2021 11:24:23] "GET /Lib/site-packages/app/init.py?v=1637231063687 HTTP/1.1" 404 -

Loading widget forever running

Note : I have npm with vuejs3 already installed (not in this directory) can it causes problems ?

Proper way to integrate a Javascript Vue plugin

I'm not clear how to wrap and integrate a Vue.js plugin from the docs.

I've got the following:

# plugins/socketio.py
from browser import window
from vue import Vue
from vue.decorators.base import VueDecorator, pyjs_bridge

def install(socketio=None):
    SocketIO = window.io
    VueSocketIO = window.VueSocketIO

    socketio = socketio or SocketIO()
    Vue.use(VueSocketIO.new({
        'debug': True,
        'connection': socketio,
    }))

class Sockets(VueDecorator):
    __key__ = "sockets"

    def __init__(self, fn):
        self.fn = fn
        self.__id__ = fn.__name__
        self.__value__ = pyjs_bridge(fn, inject_vue_instance=True)

def sockets(fn):
    return Sockets(fn)
# app.py
from vue import VueComponent
from . import plugins

class App(VueComponent):
    template = '''
        <div class="container">
            <router-view></router-view>
        </div>
    '''

plugins.socketio.install()

App("#app")

I'm not sure if I should use VuePlugin or some other method.

Along with this, VueSocketIO can receive a dict of options, I'm not sure how this would be passed in?

Error when integrating with vue-socketio

I've got a basic integration of vue-socketio working using a VueDecorator.

Code to integrate is as follows:

# vue-socketio integration
from browser import window
from vue.decorators.base import VueDecorator

SocketIO = window.io
VueSocketIO = window.VueSocketIO

socket = SocketIO()
Vue.use(VueSocketIO.new({
    'debug': True,
    'connection': socket,
}))

class Sockets(VueDecorator):
    __key__ = "sockets"

    def __init__(self, fn):
        self.fn = fn
        self.__id__ = fn.__name__
        self.__value__ = pyjs_bridge(fn, inject_vue_instance=True)

def sockets(fn):
    return Sockets(fn)
# basic example usage with "connect" callback
from vue import VueComponent

class App(VueComponent):
    template = '''
        <div class="container">
            <router-view></router-view>
        </div>
    '''

    @sockets
    def connect(self, *args, **kwargs):
        print('CONNECTED')

App("#app")

When I run my code however, I get the following warning:

vue-socketio.js:10 Vue-Socket.io: #connect subscribe, component: undefined 
vue.js:634 [Vue warn]: Error in mounted hook: "Error: callback must be a function"

(found in <Root>)

vue.js:1906 Error: callback must be a function

vue-socketio.js:10 Vue-Socket.io: Broadcasting: #connect, Data: 
brython.min.js:7 CONNECTED 

I'm not sure what is different here to the other examples (Data, Computed, etc).

Mixin pattern use case

I've tested latest master changes with Mixin pattern (Regular Python mixins). Looks like only VueComponent children could be used as Mixins. Is it expected behaviour?

class FatherMixIn:
    @computed
    def my_computed(self):
        return 'Father'


class TemplateMixIn:
    template = '<div>Hello {{ my_computed }}!</div>'


class Child(FatherMixIn, TemplateMixIn, VueComponent):
    pass


Child('#app')

Error:

Error for module app
vuepy.js:9262 module {__class__: {…}, __name__: 'app', __doc__: {…}, __package__: '', __loader__: {…}, …}
vuepy.js:9263 $B.parser.$Node {type: 'module', children: Array(5), yield_atoms: Array(0), add: ƒ, insert: ƒ, …}
vuepy.js:9264 Error
    at _b_.AttributeError.$factory (eval at $make_exc (vuepy.js:7929:5), <anonymous>:41:354)
    at attr_error (vuepy.js:6844:26)
    at $B.$getattr (vuepy.js:6960:1)
    at get_wrapper_base21 (eval at run_py (vuepy.js:9261:14), <anonymous>:497:94)
    at f (vuepy.js:6598:30)
    at method (vuepy.js:6602:58)
    at get_wrapper_base21 (eval at run_py (vuepy.js:9261:14), <anonymous>:507:84)
    at f (vuepy.js:6598:30)
    at method (vuepy.js:6602:58)
    at __init__22 (eval at run_py (vuepy.js:9261:14), <anonymous>:582:374)
vuepy.js:9266 args ["'FatherMixIn' object has no attribute '__base__'", __class__: {…}, __brython__: true, __dict__: {…}]
vuepy.js:9266 __class__ {__class__: {…}, __mro__: Array(3), $is_class: true, $infos: {…}, $factory: ƒ, …}
vuepy.js:9266 $py_error true
vuepy.js:9266 $stack (8) [Array(4), Array(4), Array(5), Array(5), Array(5), Array(5), Array(5), Array(5)]
vuepy.js:9266 $line_info 63,vue.factory
vuepy.js:9266 __cause__ {__class__: {…}, __hashvalue__: 0}
vuepy.js:9266 __context__ {__class__: {…}, __hashvalue__: 0}
vuepy.js:9266 __suppress_context__ false
vuepy.js:9267 Traceback (most recent call last):
  File http://127.0.0.1:5000/__main__ line 1, in <module>
    import app
  File http://127.0.0.1:5000/app.py line 38, in <module>
    Child('#app')
  File http://127.0.0.1:5000/vue/vue.py line 64, in __new__
    init_dict = cls.init_dict()
  File http://127.0.0.1:5000/vue/vue.py line 61, in init_dict
    return VueComponentFactory.get_item(cls)
  File http://127.0.0.1:5000/vue/factory.py line 58, in get_item
    return cls(wrapper).generate_item()
  File http://127.0.0.1:5000/vue/factory.py line 70, in __init__
    self.base = self.get_wrapper_base(wrapper)
  File http://127.0.0.1:5000/vue/factory.py line 66, in get_wrapper_base
    return cls.get_wrapper_base(base)
  File http://127.0.0.1:5000/vue/factory.py line 63, in get_wrapper_base
    base = wrapper.__base__
vuepy.js:9268 message: undefined
vuepy.js:9269 filename: undefined
vuepy.js:9270 linenum: undefined
vuepy.js:9271 line info undefined
vuepy.js:5380 handle error {__class__: {…}, __mro__: Array(3), $is_class: true, $infos: {…}, $factory: ƒ, …} ["'FatherMixIn' object has no attribute '__base__'", __class__: {…}, __brython__: true, __dict__: {…}]
vuepy.js:6254 Traceback (most recent call last):
  File http://127.0.0.1:5000/__main__ line 1, in <module>
    import app
  File http://127.0.0.1:5000/app.py line 38, in <module>
    Child('#app')
  File http://127.0.0.1:5000/vue/vue.py line 64, in __new__
    init_dict = cls.init_dict()
  File http://127.0.0.1:5000/vue/vue.py line 61, in init_dict
    return VueComponentFactory.get_item(cls)
  File http://127.0.0.1:5000/vue/factory.py line 58, in get_item
    return cls(wrapper).generate_item()
  File http://127.0.0.1:5000/vue/factory.py line 70, in __init__
    self.base = self.get_wrapper_base(wrapper)
  File http://127.0.0.1:5000/vue/factory.py line 66, in get_wrapper_base
    return cls.get_wrapper_base(base)
  File http://127.0.0.1:5000/vue/factory.py line 63, in get_wrapper_base
    base = wrapper.__base__
AttributeError: 'FatherMixIn' object has no attribute '__base__'
vuepy.js:5380 handle error {__class__: {…}, __mro__: Array(3), $is_class: true, $infos: {…}, $factory: ƒ, …} ["'FatherMixIn' object has no attribute '__base__'", __class__: {…}, __brython__: true, __dict__: {…}]
vuepy.js:6254 Traceback (most recent call last):
  File http://127.0.0.1:5000/__main__ line 1, in <module>
    import app
  File http://127.0.0.1:5000/app.py line 38, in <module>
    Child('#app')
  File http://127.0.0.1:5000/vue/vue.py line 64, in __new__
    init_dict = cls.init_dict()
  File http://127.0.0.1:5000/vue/vue.py line 61, in init_dict
    return VueComponentFactory.get_item(cls)
  File http://127.0.0.1:5000/vue/factory.py line 58, in get_item
    return cls(wrapper).generate_item()
  File http://127.0.0.1:5000/vue/factory.py line 70, in __init__
    self.base = self.get_wrapper_base(wrapper)
  File http://127.0.0.1:5000/vue/factory.py line 66, in get_wrapper_base
    return cls.get_wrapper_base(base)
  File http://127.0.0.1:5000/vue/factory.py line 63, in get_wrapper_base
    base = wrapper.__base__
AttributeError: 'FatherMixIn' object has no attribute '__base__'
vuepy.js:5389 Uncaught Error
    at _b_.AttributeError.$factory (eval at $make_exc (vuepy.js:7929:5), <anonymous>:41:354)
    at attr_error (vuepy.js:6844:26)
    at $B.$getattr (vuepy.js:6960:1)
    at get_wrapper_base21 (eval at run_py (vuepy.js:9261:14), <anonymous>:497:94)
    at f (vuepy.js:6598:30)
    at method (vuepy.js:6602:58)
    at get_wrapper_base21 (eval at run_py (vuepy.js:9261:14), <anonymous>:507:84)
    at f (vuepy.js:6598:30)
    at method (vuepy.js:6602:58)
    at __init__22 (eval at run_py (vuepy.js:9261:14), <anonymous>:582:374)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.