Closed Tset-Noitamotua closed 4 months ago
Most examples of the use of frameworks are contributed by users. If anyone contributes a good example, probably we'll include it in the distro.
KR Jacques
I'm trying but I'm running into an issue - I've created an object by instantiating a class and passing this object to Vue, I'm getting an infinite look (recursion limit) I think it's looping over __metaclass__
.
How to aproach this issue? Thanks!
Could you show me some code in order to be able to help you?
Sure! I'm writing a module for Nuxtjs which will allow to write Nuxt apps with Python / Transcrypt. But I've currently only been able to produce the required object with Javascripthon.
Please check out:
https://github.com/nuxt-community/python-module/blob/transcrypt_example/example/pages/transcrypt.vue
It is a single file component with Transcrypt syntax. Since Vue is rather functional, Python may not be the best match for producing the required objects (docs at https://vuejs.org/v2/guide/ )
Here's also the relevant Nuxt docs. Nuxt is a framework which uses the filesystem as routes to serve .vue files, single file components. For better documentation of the issue here's the clean code achieved with Javascripthon:
<script lang="py">
from ..components.PythonLogo import __default__ as PythonLogo
from ..components.NuxtLogo import __default__ as NuxtLogo
class Component:
def __init__(self):
self['components'] = { 'NuxtLogo': NuxtLogo, 'PythonLogo': PythonLogo }
self['data'] = lambda: {
'name': 'Nuxt.js + Python',
'description': 'Build Nuxt.js applications using Python!'
}
self['methods'] = {
'increment': self.increment,
'decrement': self.decrement
}
def increment(self):
self['$store'].commit('increment')
def decrement(self):
self['$store'].commit('decrement')
__default__= Component()
</script>
While with Transcrypt I'm using this and getting errors:
<script lang="py?compiler=transcrypt">
__pragma__('jsiter')
PythonLogo = require ('@/components/PythonLogo')['default']
NuxtLogo = require ('@/components/NuxtLogo')['default']
def increment(self):
console.log(self)
this['$store'].commit('increment')
def decrement(self):
console.log(this)
this['$store'].commit('decrement')
c = {} # __: jsiter
c['components'] = { 'NuxtLogo': NuxtLogo, 'PythonLogo': PythonLogo }
c['data'] = lambda: {
'name': 'Nuxt.js + Python',
'description': 'Build Nuxt.js applications using Python!'
}
c['methods'] = {
'increment': increment,
'decrement': decrement
}
module.exports = c
</script>
Getting:
client.js?name=client&reload=true&timeout=30000&path=/__webpack_hmr:87 [HMR] connected
vue-meta.js:502 Uncaught RangeError: Maximum call stack size exceeded
at eval (vue-meta.js:502)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
at eval (vue-meta.js:517)
at Array.reduce (<anonymous>)
at escape (vue-meta.js:502)
...
I must say I've currently no idea what's going on and why. This is because I don't know anything about Vue.
But the code in the Javascripthon example looks a lot more Pythonic than the Transcrypt code. Why is that? Can't you use a class there as well? And why are the two jsiter pragma's necessary. They are meant for very uncommon cases.
The error report indeeds signals infinite recursion. But what is vue-meta.js? Is it generated from the Transcrypt code? Do you perhaps need components, as described in:
Sorry for all these utterly uninformed questions, but I have no concept of how this is supposed to work, so I try to explore the playfield...
Jaques,
Here's what we are actually trying to accomplish.
It is an object that will hold functional behaviour of the web component at hand.
I've found it's tricky to produce this object with Python syntax. Any idea for it would be cool.
Also I've found Transcrypt works with Nuxt only in SPA mode, server side rendering doesn't work as something in Transcrypt wants to access the window
object.
If you check out the https://github.com/nuxt-community/python-module/tree/transcrypt_example (transcrypt_example branch), i've just added this javascript example.
When you run with npm run dev
you'll get routes / with pj
, /transcrypt with transcrypt
and /javascript with this example.
<script>
import PythonLogo from '~/components/PythonLogo'
import NuxtLogo from '~/components/NuxtLogo'
export default {
components : { 'NuxtLogo': NuxtLogo, 'PythonLogo': PythonLogo },
data: function () {
return {
'name': 'Nuxt.js + Python',
'description': 'Build Nuxt.js applications using Python!'
}
},
methods: {
increment: function() {
this['$store'].commit('increment')
},
decrement: function() {
this['$store'].commit('decrement')
}
}
}
</script>
It's necessary to launch the example with nuxt --spa example/
in order to try SPA mode or it will fail.
I 've tried to install the example but unfortunately the installation fails on my Windows 10 machine.
But already one hint:
To keep Transcrypt from referencing the global Window object, take a look at the -p .none
switch,
that's also used when compiling server side applications for node.js.
Tranlated from your JavaScript example a sugggestion would be (currently no idea if it really works):
<script lang="py?compiler=transcrypt">
__pragma__ ('js', '{}', '''
import PythonLogo from '~/components/PythonLogo';
import NuxtLogo from '~/components/NuxtLogo';
''')
class MyClass:
def __init__ (self):
self.components = {'NuxtLogo': NuxtLogo, 'PythonLogo': PythonLogo}
def data (self):
return {
'name': 'Nuxt.js + Python',
'description': 'Build Nuxt.js applications using Python!'
}
def increment (self):
self ['$store'].commit('increment')
def decrement (self):
self ['$store'].commit('decrement')
__pragma ('js', '', ''')
export default {MyClass ()};
''')
</script>
To make the whole thing lean when multiple components are used on a page, probably you need to use Transcrypt units. This avoids duplicating the runtime and other common code.
As mentioned earlier, units (components) are described at:
Sorry my help isn't more concrete, but I currently lack the Vue knowledge for that.
@icarito I had previously used Vue, Browserify with Transcrypt, it worked, but I didn't use webpack, so it seems you just need a plain old JS object, Python can implement functions, you don't need classes, Vue is rather functional.
Dear All I am not a vue expert but have been hacking my way through this problem last few days. I have also come to the same conclusion that vue needs functions not classes. However we still need to encapsulate this within a class to not pollute the global name space. This is a small excerpt from the work I am doing. I was able to compile a component and make it work quite well.
`#This is the python file pragma('alias', 'jq', '$') pragma('alias', 'this_items', 'this.items') pragma('kwargs') pragma('alias', 'print', 'console.log')
from .template import comp_template
class my_comp(): props = ['api']
@staticmethod
def data():
return {'showSearch': False,
'items': [],
'selectedItems': [], 'filter': '', 'count': 0,
'fields': ['first_name', 'last_name', 'age', 'img', 'add_me']}
@staticmethod
def created():
this.init()
@staticmethod
def showSearchBox():
this.showSearch = not this.showSearch
@staticmethod
def addMe(data):
this.selectedItems.push(data)
@staticmethod
def init():
this.loadData()
@staticmethod
def loadData():
_this = this
def process_request(response):
if response.data is not None:
_this.js_items = response.data
else:
alert('RESPONSE BODY IS NONOE')
axios.js_get(this.api).then(process_request)
@staticmethod
def comp_defs():
class_handle = my_comp
methods = {'showSearchBox': class_handle.showSearchBox,
'addMe': class_handle.addMe,
'init': class_handle.init,
'loadData': class_handle.loadData}
return {'data': class_handle.data,
'props': class_handle.props,
'template': comp_template,
'created': class_handle.created,
'methods': methods}
Vue.component('vrs-search', my_comp.comp_defs()) ` I also wrote a small compilation script to incorporate an html based template for view to be incorporated into the component. This allows you to build the template in a good html ide. A bit hacky but works like a charm for me. Key thing is to be able to use "this" key word whilst maintaining some semblance of OOP tenets of python. Not using python instances at all. Hope to exchange more ideas soon.
`import argparse from subprocess import call from pathlib import Path
if name == 'main': parser = argparse.ArgumentParser() parser.add_argument("file", help="Python File") parser.add_argument("--template", "-t", help="template file")
args = parser.parse_args()
# Get the template
html = Path(args.template).read_text()
html = html.replace('\n', '\\\n').replace('\r', '\\\n')
template_py_file = open('template.py', 'w')
tpl_py = ''.join(['comp_template=', '\'', html, '\''])
print(tpl_py, file=template_py_file)
template_py_file.close()
# Define the methods
call('transcrypt -b -n %s' % (args.file))
`
I'm working on the same kind of thing. My tests with transcrypt weren't goods.
But currently, I reach to use components like that :
<template>
<div>
{{name}} {{cpt}}
<button @click="inc()">++</button>
</div>
</template>
<script lang="python">
class Component:
def __init__(self, name): # <- name is a props
self.cpt=0
def inc(self):
self.cpt+=1
</script>
<style scoped>
:scope {background:#EEE}
</style>
Currently, I've got the lifecyles, watchers, computed, props features ... I've not released it yet, but it will be in my vbuild thing Will release soon
BTW, I've just released ... my vision of "python component" in a vue/sfc file, thru vbuild (python lib to render "*.vue" -> html/script/style, without a nodejs stack).
All is here : https://github.com/manatlan/vbuild The py component part : https://github.com/manatlan/vbuild/blob/master/doc/PyComponent.md
It's pretty usable (I use it in production)
@manatlan What would you need in Transcrypt (enhancements, fixes) to make vbuild work with Transcrypt?
I've made tests with the 3 main currents transpilers (transcrypt, javascrypthon and pscript). I want to keep vbuild py2/py3 compliant (I use it mainly on appengine/py27 (but will go with py37 soon)) transcrypt seems to be a command line only. I needed to do hacks to call it from python code. And AFAIK, it's not py2 & py3 compatible. Javascrypthon is py3 only, but callable easily with python. pscript works with py2 & py3 ootb, and is simple, and callable from python (but miss decorators support ... but reach to bypass this limitation by using conventions names, which is less verbose too (good point)).
btw, python components doesn't need all py std lib ... and pscript seems to do the minimal which fit the needs. (and will support decorators soon)
Hi @manatlan thanks for pointing me to wuy and vbuild, and PScript, hadn't seen it! What I like most about Javascripthon is source maps :-D
your welcome...
btw, i've just released a vbuild demo, so you can EASILY test python/pscript rendering of python components, in a vuejs context ! (the demo is, himself, a vuejs python component)
Closing as answered
Do you plan to provide some Vue examples?