bugfix
This commit is contained in:
parent
3cdbf6183a
commit
4af076798a
@ -1,4 +1,3 @@
|
|||||||
<<<<<<< HEAD
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import codecs
|
import codecs
|
||||||
@ -111,10 +110,7 @@ class Blocks(EventDispatcher):
|
|||||||
self.register_event_type('on_failed')
|
self.register_event_type('on_failed')
|
||||||
self.env = GlobalEnv()
|
self.env = GlobalEnv()
|
||||||
config = getConfig()
|
config = getConfig()
|
||||||
if config.script_root:
|
self.script = Script()
|
||||||
self.script = Script(config.script_root)
|
|
||||||
else:
|
|
||||||
self.script = Script(config.workdir)
|
|
||||||
|
|
||||||
def set(self, k:str, v):
|
def set(self, k:str, v):
|
||||||
self.env[k] = v
|
self.env[k] = v
|
||||||
@ -415,7 +411,7 @@ class Blocks(EventDispatcher):
|
|||||||
p.update(d)
|
p.update(d)
|
||||||
opts['options'] = p
|
opts['options'] = p
|
||||||
def doit(target:Widget, add_mode:str, o, w:Widget):
|
def doit(target:Widget, add_mode:str, o, w:Widget):
|
||||||
if isinstance(w, ModalView):
|
if isinstance(w, Modal):
|
||||||
return
|
return
|
||||||
|
|
||||||
if target and not w.parent:
|
if target and not w.parent:
|
||||||
@ -724,7 +720,7 @@ class Blocks(EventDispatcher):
|
|||||||
children = [i for i in from_widget.children]
|
children = [i for i in from_widget.children]
|
||||||
if hasattr(from_widget, 'get_subwidgets'):
|
if hasattr(from_widget, 'get_subwidgets'):
|
||||||
children = from_widget.get_subwidgets()
|
children = from_widget.get_subwidgets()
|
||||||
Logger.info('children=%s', str(children))
|
# Logger.info('children=%s', str(children))
|
||||||
for c in children:
|
for c in children:
|
||||||
ret = _find_widget(name, from_widget=c, dir=dir)
|
ret = _find_widget(name, from_widget=c, dir=dir)
|
||||||
if ret:
|
if ret:
|
||||||
@ -819,822 +815,3 @@ class {{ classname }}({% for b in bases -%}{{b}}{% endfor %})
|
|||||||
Factory.register('Blocks',Blocks)
|
Factory.register('Blocks',Blocks)
|
||||||
Factory.register('Video',Video)
|
Factory.register('Video',Video)
|
||||||
Factory.register('OrientationLayout', OrientationLayout)
|
Factory.register('OrientationLayout', OrientationLayout)
|
||||||
=======
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import codecs
|
|
||||||
# import ujson as json
|
|
||||||
try:
|
|
||||||
import ujson as json
|
|
||||||
except:
|
|
||||||
import json
|
|
||||||
from traceback import print_exc
|
|
||||||
|
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
from appPublic.dictExt import dictExtend
|
|
||||||
from appPublic.folderUtils import ProgramPath
|
|
||||||
from appPublic.dictObject import DictObject
|
|
||||||
from appPublic.Singleton import SingletonDecorator, GlobalEnv
|
|
||||||
from appPublic.datamapping import keyMapping
|
|
||||||
from appPublic.registerfunction import RegisterFunction
|
|
||||||
|
|
||||||
from kivy.logger import Logger
|
|
||||||
from kivy.config import Config
|
|
||||||
from kivy.metrics import sp,dp,mm
|
|
||||||
from kivy.core.window import WindowBase, Window
|
|
||||||
from kivy.properties import BooleanProperty
|
|
||||||
from kivy.uix.widget import Widget
|
|
||||||
from kivy.clock import mainthread
|
|
||||||
from kivy.uix.modalview import ModalView
|
|
||||||
from kivy.app import App
|
|
||||||
from kivy.factory import Factory
|
|
||||||
from kivy.uix.video import Video
|
|
||||||
from .utils import *
|
|
||||||
from .newvideo import Video
|
|
||||||
from .orientationlayout import OrientationLayout
|
|
||||||
from .threadcall import HttpClient
|
|
||||||
from .register import *
|
|
||||||
from .script import Script, set_script_env
|
|
||||||
|
|
||||||
class WidgetNotFoundById(Exception):
|
|
||||||
def __init__(self, id):
|
|
||||||
super().__init__()
|
|
||||||
self.idstr = id
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "Widget not found by id:" + self.idstr + ':'
|
|
||||||
|
|
||||||
def __expr__(self):
|
|
||||||
return str(self)
|
|
||||||
|
|
||||||
class ClassMethodNotFound(Exception):
|
|
||||||
def __init__(self,k,m):
|
|
||||||
super().__init__()
|
|
||||||
self.kname = k
|
|
||||||
self.mname = m
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
s = 'Method(%s) not found in class(%s)' % (self.mname,
|
|
||||||
str(self.kname.__classname__))
|
|
||||||
return s
|
|
||||||
|
|
||||||
def __expr__(self):
|
|
||||||
return self.__str__()
|
|
||||||
|
|
||||||
|
|
||||||
class NotExistsObject(Exception):
|
|
||||||
def __init__(self,name):
|
|
||||||
super().__init__()
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
s = 'not exists widget(%s)' % self.name
|
|
||||||
return s
|
|
||||||
|
|
||||||
def __expr__(self):
|
|
||||||
return self.__str__()
|
|
||||||
|
|
||||||
class ArgumentError(Exception):
|
|
||||||
def __init__(self,argument,desc):
|
|
||||||
super().__init__()
|
|
||||||
self.argument = argument
|
|
||||||
self.desc = desc
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
s = 'argument(%s) missed:%s' % (self.argument,self.desc)
|
|
||||||
return s
|
|
||||||
|
|
||||||
def __expr__(self):
|
|
||||||
return self.__str__()
|
|
||||||
|
|
||||||
|
|
||||||
class NotRegistedWidget(Exception):
|
|
||||||
def __init__(self, name:str):
|
|
||||||
super().__init__()
|
|
||||||
self.widget_name = name
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
s = 'not reigsted widget(%s)' % self.name
|
|
||||||
return s
|
|
||||||
|
|
||||||
def __expr__(self):
|
|
||||||
return self.__str__()
|
|
||||||
|
|
||||||
def registerWidget(name:str,widget):
|
|
||||||
globals()[name] = widget
|
|
||||||
|
|
||||||
|
|
||||||
class Blocks(EventDispatcher):
|
|
||||||
def __init__(self):
|
|
||||||
EventDispatcher.__init__(self)
|
|
||||||
self.action_id = 0
|
|
||||||
self.register_event_type('on_built')
|
|
||||||
self.register_event_type('on_failed')
|
|
||||||
self.env = GlobalEnv()
|
|
||||||
config = getConfig()
|
|
||||||
self.script = Script()
|
|
||||||
|
|
||||||
def set(self, k:str, v):
|
|
||||||
self.env[k] = v
|
|
||||||
|
|
||||||
def register_widget(self, name:str, widget:Widget):
|
|
||||||
globals()[name] = widget
|
|
||||||
|
|
||||||
def buildAction(self, widget:Widget, desc):
|
|
||||||
conform_desc = desc.get('conform')
|
|
||||||
blocks = Blocks()
|
|
||||||
if not conform_desc:
|
|
||||||
return partial(blocks.uniaction, widget, desc)
|
|
||||||
func =partial(blocks.conform_action,widget, desc)
|
|
||||||
return func
|
|
||||||
|
|
||||||
def eval(self, s:str, l:dict):
|
|
||||||
g = {}
|
|
||||||
forbidens = [
|
|
||||||
"os",
|
|
||||||
"sys",
|
|
||||||
"codecs",
|
|
||||||
"json",
|
|
||||||
]
|
|
||||||
|
|
||||||
for k,v in globals().copy().items():
|
|
||||||
if k not in forbidens:
|
|
||||||
g[k] = v
|
|
||||||
|
|
||||||
"""
|
|
||||||
g['__builtins__'] = globals()['__builtins__']
|
|
||||||
g['__builtins__']['__import__'] = None
|
|
||||||
g['__builtins__']['__loader__'] = None
|
|
||||||
g['__builtins__']['open'] = None
|
|
||||||
"""
|
|
||||||
g.update(self.env)
|
|
||||||
return eval(s,g,l)
|
|
||||||
|
|
||||||
def getUrlData(self, url:str, method:str='GET',
|
|
||||||
params:dict={}, files:dict={},
|
|
||||||
callback=None,
|
|
||||||
errback=None,**kw):
|
|
||||||
|
|
||||||
if url is None:
|
|
||||||
if errback:
|
|
||||||
errback(None,Exception('url is None'))
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if url.startswith('file://'):
|
|
||||||
return self.script.dispatch(url, **params)
|
|
||||||
elif url.startswith('http://') or url.startswith('https://'):
|
|
||||||
try:
|
|
||||||
hc = HttpClient()
|
|
||||||
resp=hc(url,method=method,params=params,files=files)
|
|
||||||
# print('Blocks.py :resp=',resp)
|
|
||||||
return resp
|
|
||||||
except Exception as e:
|
|
||||||
print_exc()
|
|
||||||
if errback:
|
|
||||||
return errback(None,e)
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
config = getConfig()
|
|
||||||
url = config.uihome + url
|
|
||||||
return self.getUrlData(url,method=method,
|
|
||||||
params=params,
|
|
||||||
files=files,
|
|
||||||
**kw)
|
|
||||||
|
|
||||||
def strValueExpr(self,s:str,localnamespace:dict={}):
|
|
||||||
if not s.startswith('py::'):
|
|
||||||
return s
|
|
||||||
s = s[4:]
|
|
||||||
try:
|
|
||||||
v = self.eval(s,localnamespace)
|
|
||||||
return v
|
|
||||||
except Exception as e:
|
|
||||||
print('Exception .... ',e,'script=',s)
|
|
||||||
print_exc()
|
|
||||||
return s
|
|
||||||
|
|
||||||
def arrayValueExpr(self,arr:list,localnamespace:dict={}) -> list:
|
|
||||||
d = []
|
|
||||||
for v in arr:
|
|
||||||
if type(v) == type(''):
|
|
||||||
d.append(self.strValueExpr(v,localnamespace))
|
|
||||||
continue
|
|
||||||
if type(v) == type([]):
|
|
||||||
d.append(self.arrayValueExpr(v,localnamespace))
|
|
||||||
continue
|
|
||||||
if type(v) == type({}):
|
|
||||||
d.append(self.dictValueExpr(v,localnamespace))
|
|
||||||
continue
|
|
||||||
if type(v) == type(DictObject):
|
|
||||||
d.append(self.dictValueExpr(v,localnamespace))
|
|
||||||
continue
|
|
||||||
d.append(v)
|
|
||||||
return d
|
|
||||||
|
|
||||||
def dictValueExpr(self,dic:dict,localnamespace:dict={}) -> dict:
|
|
||||||
d = {}
|
|
||||||
for k,v in dic.items():
|
|
||||||
if type(v) == type(''):
|
|
||||||
d[k] = self.strValueExpr(v,localnamespace)
|
|
||||||
continue
|
|
||||||
if type(v) == type([]):
|
|
||||||
d[k] = self.arrayValueExpr(v,localnamespace)
|
|
||||||
continue
|
|
||||||
if type(v) == type({}):
|
|
||||||
d[k] = self.dictValueExpr(v,localnamespace)
|
|
||||||
continue
|
|
||||||
if type(v) == type(DictObject):
|
|
||||||
d[k] = self.dictValueExpr(v,localnamespace)
|
|
||||||
continue
|
|
||||||
d[k] = v
|
|
||||||
return d
|
|
||||||
def valueExpr(self,obj,localnamespace:dict={}):
|
|
||||||
if type(obj) == type(''):
|
|
||||||
return self.strValueExpr(obj,localnamespace)
|
|
||||||
if type(obj) == type([]):
|
|
||||||
return self.arrayValueExpr(obj,localnamespace)
|
|
||||||
if type(obj) == type({}):
|
|
||||||
return self.dictValueExpr(obj,localnamespace)
|
|
||||||
if isinstance(obj,DictObject):
|
|
||||||
return self.dictValueExpr(obj,localnamespace)
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def w_build(self,desc) -> Widget:
|
|
||||||
widgetClass = desc.get('widgettype',None)
|
|
||||||
if not widgetClass:
|
|
||||||
Logger.info("Block: w_build(), desc invalid", desc)
|
|
||||||
raise Exception(desc)
|
|
||||||
|
|
||||||
widgetClass = desc['widgettype']
|
|
||||||
opts = self.valueExpr(desc.get('options',{}).copy())
|
|
||||||
widget = None
|
|
||||||
try:
|
|
||||||
klass = Factory.get(widgetClass)
|
|
||||||
widget = klass(**opts)
|
|
||||||
except Exception as e:
|
|
||||||
print('Error:',widgetClass,'contructon error')
|
|
||||||
print_exc()
|
|
||||||
raise NotExistsObject(widgetClass)
|
|
||||||
|
|
||||||
if desc.get('id'):
|
|
||||||
id = desc.get('id')
|
|
||||||
if id.startswith('app.'):
|
|
||||||
app = App.get_running_app()
|
|
||||||
id = id[4:]
|
|
||||||
setattr(app, id, widget)
|
|
||||||
if id.startswith('root.'):
|
|
||||||
app = App.get_running_app()
|
|
||||||
id = id[5:]
|
|
||||||
setattr(app.root, id, widget)
|
|
||||||
|
|
||||||
if '.' in id:
|
|
||||||
Logger.info('widget id(%s) can not contain "."', id)
|
|
||||||
else:
|
|
||||||
widget.widget_id = id
|
|
||||||
|
|
||||||
widget.build_desc = desc
|
|
||||||
self.build_attributes(widget, desc)
|
|
||||||
self.build_rest(widget, desc)
|
|
||||||
self.buildBinds(widget, desc)
|
|
||||||
return widget
|
|
||||||
|
|
||||||
def build_attributes(self, widget:Widget,desc,t=None):
|
|
||||||
excludes = ['widgettype','options','subwidgets','binds']
|
|
||||||
for k,v in [(k,v) for k,v in desc.items() if k not in excludes]:
|
|
||||||
if isinstance(v,dict) and v.get('widgettype'):
|
|
||||||
b = Blocks()
|
|
||||||
v = self.valueExpr(v, localnamespace={'self':widget})
|
|
||||||
w = b.widgetBuild(v)
|
|
||||||
if hasattr(widget,k):
|
|
||||||
aw = getattr(widget,k)
|
|
||||||
if isinstance(aw,Layout):
|
|
||||||
aw.add_widget(w)
|
|
||||||
continue
|
|
||||||
setattr(widget,k,w)
|
|
||||||
continue
|
|
||||||
setattr(widget,k,self.valueExpr(v,\
|
|
||||||
localnamespace={'self':widget}))
|
|
||||||
|
|
||||||
def build_rest(self, widget:Widget,desc,t=None):
|
|
||||||
self.subwidget_total = len(desc.get('subwidgets',[]))
|
|
||||||
self.subwidgets = [ None for i in range(self.subwidget_total)]
|
|
||||||
pos = 0
|
|
||||||
for pos,sw in enumerate(desc.get('subwidgets',[])):
|
|
||||||
b = Blocks()
|
|
||||||
if isinstance(sw, str):
|
|
||||||
# w = Blocks.getWidgetById(sw, from_widget=widget)
|
|
||||||
w = Blocks.findWidget(sw, from_widget=widget)
|
|
||||||
if w:
|
|
||||||
widget.add_widget(w)
|
|
||||||
continue
|
|
||||||
|
|
||||||
kw = self.valueExpr(sw.copy(),
|
|
||||||
localnamespace={'self':widget})
|
|
||||||
w = b.widgetBuild(kw)
|
|
||||||
if w:
|
|
||||||
widget.add_widget(w)
|
|
||||||
|
|
||||||
|
|
||||||
def buildBinds(self, widget:Widget, desc:dict):
|
|
||||||
for b in desc.get('binds',[]):
|
|
||||||
kw = self.valueExpr(b.copy(), \
|
|
||||||
localnamespace={'self':widget})
|
|
||||||
self.buildBind(widget,kw)
|
|
||||||
|
|
||||||
def buildBind(self, widget:Widget, desc:dict):
|
|
||||||
wid = desc.get('wid','self')
|
|
||||||
# w = Blocks.getWidgetById(desc.get('wid','self'),from_widget=widget)
|
|
||||||
w = Blocks.findWidget(desc.get('wid','self'),from_widget=widget)
|
|
||||||
if not w:
|
|
||||||
Logger.info('Block: id(%s) %s',desc.get('wid','self'),
|
|
||||||
'not found via Blocks.getWidgetById()')
|
|
||||||
return
|
|
||||||
event = desc.get('event')
|
|
||||||
if event is None:
|
|
||||||
Logger.info('Block: binds desc miss event, desc=%s',str(desc))
|
|
||||||
return
|
|
||||||
f = self.buildAction(widget,desc)
|
|
||||||
if f is None:
|
|
||||||
Logger.info('Block: get a null function,%s',str(desc))
|
|
||||||
return
|
|
||||||
w.bind(**{event:f})
|
|
||||||
|
|
||||||
def multipleAction(self, widget:Widget, desc, *args):
|
|
||||||
desc1 = {k:v for k, v in desc.items() if k != 'actions'}
|
|
||||||
mydesc = desc1.copy()
|
|
||||||
for a in desc['actions']:
|
|
||||||
new_desc = mydesc.copy()
|
|
||||||
new_desc.update(a)
|
|
||||||
self.uniaction(widget,new_desc, *args)
|
|
||||||
|
|
||||||
def conform_action(self, widget:Widget, desc, *args):
|
|
||||||
conform_desc = desc.get('conform')
|
|
||||||
blocks = Blocks()
|
|
||||||
if not conform_desc:
|
|
||||||
blocks.uniaction(widget, desc,*args, **kw)
|
|
||||||
return
|
|
||||||
w = blocks.widgetBuild({
|
|
||||||
"widgettype":"Conform",
|
|
||||||
"options":conform_desc
|
|
||||||
})
|
|
||||||
w.bind(on_conform=partial(blocks.uniaction, widget, desc))
|
|
||||||
w.open()
|
|
||||||
|
|
||||||
def uniaction(self, widget:Widget, desc, *args):
|
|
||||||
acttype = desc.get('actiontype')
|
|
||||||
if acttype=='blocks':
|
|
||||||
return self.blocksAction(widget,desc, *args)
|
|
||||||
if acttype=='urlwidget':
|
|
||||||
return self.urlwidgetAction(widget,desc, *args)
|
|
||||||
if acttype == 'registedfunction':
|
|
||||||
return self.registedfunctionAction(widget,desc, *args)
|
|
||||||
if acttype == 'script':
|
|
||||||
return self.scriptAction(widget, desc, *args)
|
|
||||||
if acttype == 'method':
|
|
||||||
return self.methodAction(widget, desc, *args)
|
|
||||||
if acttype == 'event':
|
|
||||||
return self.eventAction(widget, desc, *args)
|
|
||||||
if acttype == 'multiple':
|
|
||||||
return self.multipleAction(widget, desc, *args)
|
|
||||||
|
|
||||||
alert("actiontype(%s) invalid" % acttype,title='error')
|
|
||||||
|
|
||||||
def eventAction(self, widget:Widget, desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
event = desc.get('dispatch_event')
|
|
||||||
if not event:
|
|
||||||
Logger.info('Block: eventAction():desc(%s) miss dispatch_event',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
params = desc.get('params',{})
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
if d:
|
|
||||||
params.update(d)
|
|
||||||
try:
|
|
||||||
target.dispatch(event, params)
|
|
||||||
except Exception as e:
|
|
||||||
Logger.info(f'Block: eventAction():dispatch {event} error')
|
|
||||||
print_exc()
|
|
||||||
return
|
|
||||||
|
|
||||||
def get_target(self, widget:Widget, desc):
|
|
||||||
if not desc.get('target'):
|
|
||||||
return None
|
|
||||||
# return Blocks.getWidgetById(desc.get('target'),from_widget=widget)
|
|
||||||
return Blocks.findWidget(desc.get('target'),from_widget=widget)
|
|
||||||
|
|
||||||
def blocksAction(self, widget:Widget, desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
add_mode = desc.get('mode','replace')
|
|
||||||
opts = desc.get('options').copy()
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
p = opts.get('options',{}).copy()
|
|
||||||
if d:
|
|
||||||
p.update(d)
|
|
||||||
opts['options'] = p
|
|
||||||
def doit(target:Widget, add_mode:str, o, w:Widget):
|
|
||||||
if isinstance(w, Modal):
|
|
||||||
return
|
|
||||||
|
|
||||||
if target and not w.parent:
|
|
||||||
if add_mode == 'replace':
|
|
||||||
target.clear_widgets()
|
|
||||||
target.add_widget(w)
|
|
||||||
|
|
||||||
def doerr(o,e):
|
|
||||||
Logger.info('Block: blocksAction(): desc=%s widgetBuild error'
|
|
||||||
,str(desc))
|
|
||||||
raise e
|
|
||||||
|
|
||||||
b = Blocks()
|
|
||||||
b.bind(on_built=partial(doit,target,add_mode))
|
|
||||||
b.bind(on_failed=doerr)
|
|
||||||
b.widgetBuild(opts)
|
|
||||||
|
|
||||||
def urlwidgetAction(self, widget:Widget, desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
add_mode = desc.get('mode','replace')
|
|
||||||
opts = desc.get('options', {}).copy()
|
|
||||||
p1 = opts.get('params',{})
|
|
||||||
p = {}
|
|
||||||
if p1:
|
|
||||||
p.update(p1)
|
|
||||||
if len(args) >= 1 and isinstance(args[0],dict):
|
|
||||||
p.update(args[0])
|
|
||||||
d = self.getActionData(widget, desc, *args)
|
|
||||||
if d:
|
|
||||||
p.update(d)
|
|
||||||
opts['params'] = p
|
|
||||||
d = {
|
|
||||||
'widgettype' : 'urlwidget',
|
|
||||||
'options': opts
|
|
||||||
}
|
|
||||||
|
|
||||||
def doit(target:Widget, add_mode:str, o, w:Widget):
|
|
||||||
if isinstance(w, ModalView):
|
|
||||||
return
|
|
||||||
|
|
||||||
if target and not w.parent:
|
|
||||||
if add_mode == 'replace':
|
|
||||||
target.clear_widgets()
|
|
||||||
target.add_widget(w)
|
|
||||||
|
|
||||||
def doerr(o,e):
|
|
||||||
Logger.info('Block: urlwidgetAction(): desc=%s widgetBuild error'
|
|
||||||
,str(desc))
|
|
||||||
|
|
||||||
b = Blocks()
|
|
||||||
b.bind(on_built=partial(doit,target,add_mode))
|
|
||||||
b.bind(on_failed=doerr)
|
|
||||||
b.widgetBuild(d)
|
|
||||||
|
|
||||||
def getActionData(self, widget:Widget, desc, *args):
|
|
||||||
data = {}
|
|
||||||
rtdesc = self.build_rtdesc(desc)
|
|
||||||
if rtdesc:
|
|
||||||
rt = self.get_rtdata(widget, rtdesc, *args)
|
|
||||||
if rt:
|
|
||||||
data.update(rt)
|
|
||||||
if desc.get('keymapping'):
|
|
||||||
data = keyMapping(data, desc.get('keymapping'))
|
|
||||||
Logger.info('getActionData():rtdesc=%s, data=%s', rtdesc, data)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def registedfunctionAction(self, widget:Widget, desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
rf = RegisterFunction()
|
|
||||||
name = desc.get('rfname')
|
|
||||||
func = rf.get(name)
|
|
||||||
if func is None:
|
|
||||||
Logger.info('Block: desc=%s rfname(%s) not found',
|
|
||||||
str(desc), name)
|
|
||||||
raise Exception('rfname(%s) not found' % name)
|
|
||||||
|
|
||||||
params = desc.get('params',{}).copy()
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
if d:
|
|
||||||
params.update(d)
|
|
||||||
func(target, *args, **params)
|
|
||||||
|
|
||||||
def scriptAction(self, widget:Widget, desc, *args):
|
|
||||||
script = desc.get('script')
|
|
||||||
if not script:
|
|
||||||
Logger.info('Block: scriptAction():desc(%s) target not found',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
ns = {
|
|
||||||
"self":target,
|
|
||||||
"args":args,
|
|
||||||
"kwargs":d
|
|
||||||
}
|
|
||||||
if d:
|
|
||||||
ns.update(d)
|
|
||||||
try:
|
|
||||||
self.eval(script, ns)
|
|
||||||
except Exception as e:
|
|
||||||
print_exc()
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
def build_rtdesc(self, desc):
|
|
||||||
rtdesc = desc.get('rtdata')
|
|
||||||
if not rtdesc:
|
|
||||||
if desc.get('datawidget'):
|
|
||||||
rtdesc = {}
|
|
||||||
rtdesc['target'] = desc['datawidget']
|
|
||||||
if desc.get('datascript'):
|
|
||||||
rtdesc['script'] = desc.get('datacript')
|
|
||||||
else:
|
|
||||||
rtdesc['method'] = desc.get('datamethod', 'getValue')
|
|
||||||
rtdesc['kwargs'] = desc.get('datakwargs', {})
|
|
||||||
return rtdesc
|
|
||||||
|
|
||||||
def get_rtdata(self, widget:Widget, desc, *args):
|
|
||||||
"""
|
|
||||||
desc descript follow attributes
|
|
||||||
{
|
|
||||||
"target", a target name from widget
|
|
||||||
"method", a method name, default is 'getValue',
|
|
||||||
"script", script to handle the data
|
|
||||||
"kwargs":" a dict arguments, default is {}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
if desc is None or desc == {}:
|
|
||||||
print('get_rtdata():desc is None')
|
|
||||||
return {}
|
|
||||||
kwargs = desc.get('kwargs', {})
|
|
||||||
if not isinstance(kwargs, dict):
|
|
||||||
kwargs = {}
|
|
||||||
w = None
|
|
||||||
if len(args) > 0:
|
|
||||||
w = args[0]
|
|
||||||
target = desc.get('target')
|
|
||||||
if target:
|
|
||||||
# w = Blocks.getWidgetById(target, from_widget=widget)
|
|
||||||
w = Blocks.findWidget(target, from_widget=widget)
|
|
||||||
if w is None:
|
|
||||||
print('get_rtdata():w is None', desc)
|
|
||||||
return {}
|
|
||||||
script = desc.get('script')
|
|
||||||
if script:
|
|
||||||
ns = {
|
|
||||||
"self":w,
|
|
||||||
"args":args,
|
|
||||||
"kwargs":kwargs
|
|
||||||
}
|
|
||||||
d = self.eval(script, ns)
|
|
||||||
return d
|
|
||||||
|
|
||||||
method = desc.get('method', 'getValue')
|
|
||||||
if not hasattr(w, method):
|
|
||||||
print('get_rtdata():method is None', desc, type(w))
|
|
||||||
return {}
|
|
||||||
f = getattr(w, method)
|
|
||||||
try:
|
|
||||||
r = f(**kwargs)
|
|
||||||
if isinstance(r, dict):
|
|
||||||
return r
|
|
||||||
if isinstance(r, DictObject):
|
|
||||||
return r.to_dict()
|
|
||||||
print('get_rtdata():method return is not dict', desc, 'ret=', r, type(r))
|
|
||||||
return {}
|
|
||||||
except:
|
|
||||||
print_exc()
|
|
||||||
return {}
|
|
||||||
|
|
||||||
def methodAction(self, widget:Widget, desc, *args):
|
|
||||||
method = desc.get('method')
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
if target is None:
|
|
||||||
Logger.info('Block: methodAction():desc(%s) target not found',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
if method is None:
|
|
||||||
Logger.info('Block: methodAction():desc(%s) method not found',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
if hasattr(target,method):
|
|
||||||
f = getattr(target, method)
|
|
||||||
kwargs = desc.get('options',{}).copy()
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
if d:
|
|
||||||
kwargs.update(d)
|
|
||||||
f(*args, **kwargs)
|
|
||||||
else:
|
|
||||||
alert('%s method not found' % method)
|
|
||||||
|
|
||||||
def widgetBuild(self, desc):
|
|
||||||
"""
|
|
||||||
desc format:
|
|
||||||
{
|
|
||||||
widgettype:<registered widget>,
|
|
||||||
id:widget id,
|
|
||||||
options:{}
|
|
||||||
subwidgets:[
|
|
||||||
]
|
|
||||||
binds:[
|
|
||||||
]
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
def doit(desc):
|
|
||||||
if isinstance(desc,DictObject):
|
|
||||||
desc = desc.to_dict()
|
|
||||||
if not isinstance(desc,dict):
|
|
||||||
Logger.info('Block: desc(%s) must be a dict object(%s)',
|
|
||||||
desc,type(desc))
|
|
||||||
return None
|
|
||||||
|
|
||||||
# desc = self.valueExpr(desc)
|
|
||||||
try:
|
|
||||||
widget = self.w_build(desc)
|
|
||||||
self.dispatch('on_built',widget)
|
|
||||||
if hasattr(widget,'ready'):
|
|
||||||
widget.ready = True
|
|
||||||
return widget
|
|
||||||
except Exception as e:
|
|
||||||
print_exc()
|
|
||||||
self.dispatch('on_failed',e)
|
|
||||||
return None
|
|
||||||
|
|
||||||
if isinstance(desc,DictObject):
|
|
||||||
desc = desc.to_dict()
|
|
||||||
if not isinstance(desc, dict):
|
|
||||||
print('widgetBuild1: desc must be a dict object',
|
|
||||||
desc,type(desc))
|
|
||||||
self.dispatch('on_failed',Exception('miss url'))
|
|
||||||
return
|
|
||||||
|
|
||||||
widgettype = desc.get('widgettype')
|
|
||||||
while widgettype == "urlwidget":
|
|
||||||
opts = desc.get('options',{}).copy()
|
|
||||||
extend = desc.get('extend')
|
|
||||||
addon = None
|
|
||||||
if desc.get('extend'):
|
|
||||||
addon = desc.get('extend').copy()
|
|
||||||
url = opts.get('url')
|
|
||||||
if url is None:
|
|
||||||
self.dispatch('on_failed',Exception('miss url'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if opts.get('url'):
|
|
||||||
del opts['url']
|
|
||||||
rtdesc = self.build_rtdesc(opts)
|
|
||||||
if rtdesc:
|
|
||||||
rtdata = self.get_rtdata(None, rtdesc)
|
|
||||||
params = opts.get('params', {})
|
|
||||||
params.update(rtdata)
|
|
||||||
opts['params'] = params
|
|
||||||
|
|
||||||
desc = self.getUrlData(url,**opts)
|
|
||||||
if not (isinstance(desc, DictObject) or \
|
|
||||||
isinstance(desc, dict)):
|
|
||||||
print('Block2: desc must be a dict object',
|
|
||||||
desc,type(desc))
|
|
||||||
self.dispatch('on_failed',Exception('miss url'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if addon:
|
|
||||||
desc = dictExtend(desc,addon)
|
|
||||||
widgettype = desc.get('widgettype')
|
|
||||||
if widgettype is None:
|
|
||||||
print('Block3: desc must be a dict object not None')
|
|
||||||
return None
|
|
||||||
return doit(desc)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def findWidget(self, id:str, from_widget:Widget=None) -> Widget:
|
|
||||||
"""
|
|
||||||
-:find up direct, find widget in ancestor
|
|
||||||
+ or empty: find down direct, find widget in descendant
|
|
||||||
@:find widget by class
|
|
||||||
$ or empty:find widget by id
|
|
||||||
.:more than one step.
|
|
||||||
|
|
||||||
"""
|
|
||||||
def find_widget_by_id(id, from_widget):
|
|
||||||
if id=='self':
|
|
||||||
return from_widget
|
|
||||||
if hasattr(from_widget,'widget_id'):
|
|
||||||
if from_widget.widget_id == id:
|
|
||||||
return from_widget
|
|
||||||
if hasattr(from_widget, id):
|
|
||||||
w = getattr(from_widget,id)
|
|
||||||
return w
|
|
||||||
return None
|
|
||||||
|
|
||||||
def find_widget_by_class(klass, from_widget):
|
|
||||||
if from_widget.__class__.__name__ == klass:
|
|
||||||
return from_widget
|
|
||||||
for k, v in from_widget.__dict__.items():
|
|
||||||
if isinstance(v, Widget):
|
|
||||||
if v.__class__.__name__ == klass:
|
|
||||||
return v
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _find_widget(name, from_widget, dir='down',
|
|
||||||
find_func=find_widget_by_id):
|
|
||||||
w = find_func(name, from_widget)
|
|
||||||
if w:
|
|
||||||
return w
|
|
||||||
if dir == 'down':
|
|
||||||
children = [i for i in from_widget.children]
|
|
||||||
if hasattr(from_widget, 'get_subwidgets'):
|
|
||||||
children = from_widget.get_subwidgets()
|
|
||||||
# Logger.info('children=%s', str(children))
|
|
||||||
for c in children:
|
|
||||||
ret = _find_widget(name, from_widget=c, dir=dir)
|
|
||||||
if ret:
|
|
||||||
return ret
|
|
||||||
else:
|
|
||||||
if isinstance(from_widget, WindowBase):
|
|
||||||
return None
|
|
||||||
if from_widget.parent:
|
|
||||||
return _find_widget(name,
|
|
||||||
from_widget=from_widget.parent,
|
|
||||||
dir=dir)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def find_widget(step, from_widget):
|
|
||||||
dir = 'down'
|
|
||||||
if step[0:1] == '-':
|
|
||||||
dir = 'up'
|
|
||||||
step = step[1:]
|
|
||||||
find_func = find_widget_by_id
|
|
||||||
if step[0:1] == '@':
|
|
||||||
step = step[1:]
|
|
||||||
find_func = find_widget_by_class
|
|
||||||
return _find_widget(step, from_widget=from_widget,
|
|
||||||
dir=dir, find_func=find_func)
|
|
||||||
|
|
||||||
steps = id.split('.')
|
|
||||||
w = from_widget
|
|
||||||
for i, s in enumerate(steps):
|
|
||||||
if i==0:
|
|
||||||
app = App.get_running_app()
|
|
||||||
fid = s
|
|
||||||
if fid == '/self' or fid == 'root':
|
|
||||||
w = app.root
|
|
||||||
if len(steps) == 1:
|
|
||||||
return from_widget
|
|
||||||
continue
|
|
||||||
if fid == 'Window':
|
|
||||||
w = Window
|
|
||||||
if len(steps) == 1:
|
|
||||||
return w
|
|
||||||
continue
|
|
||||||
if fid == 'app':
|
|
||||||
return app
|
|
||||||
|
|
||||||
w = find_widget(s, w)
|
|
||||||
if not w:
|
|
||||||
return None
|
|
||||||
return w
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def getWidgetById(self, id:str, from_widget:Widget=None) -> Widget:
|
|
||||||
return Blocks.findWidget(id, from_widget=from_widget)
|
|
||||||
|
|
||||||
def on_built(self,v=None):
|
|
||||||
return
|
|
||||||
|
|
||||||
def on_failed(self,e=None):
|
|
||||||
return
|
|
||||||
|
|
||||||
def buildKlass(self, desc):
|
|
||||||
"""
|
|
||||||
desc = {
|
|
||||||
"classname":"MyClass",
|
|
||||||
"base":["Box", "WidgetReady"],
|
|
||||||
"properties":[
|
|
||||||
{
|
|
||||||
"name":"aaa",
|
|
||||||
"type":"str",
|
|
||||||
"default":1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
"subwidgets":[
|
|
||||||
],
|
|
||||||
|
|
||||||
"""
|
|
||||||
codes = """
|
|
||||||
{% for b in bases %}
|
|
||||||
{{b}} = Factory.{{b}}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
class {{ classname }}({% for b in bases -%}{{b}}{% endfor %})
|
|
||||||
{% for p in properties %}
|
|
||||||
{{p.name}} {{p.type}}({{p.default}})
|
|
||||||
{% endfor %}
|
|
||||||
def __init__(self, **kw):
|
|
||||||
super({{classname}}, self).__init__(**kw)
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
Factory.register('Blocks',Blocks)
|
|
||||||
Factory.register('Video',Video)
|
|
||||||
Factory.register('OrientationLayout', OrientationLayout)
|
|
||||||
>>>>>>> cab6a2818466e5d32880a6a01e7afe16ad192675
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
<<<<<<< HEAD
|
|
||||||
|
|
||||||
from kivy.event import EventDispatcher
|
from kivy.event import EventDispatcher
|
||||||
from kivy.app import App
|
from kivy.app import App
|
||||||
from kivy.factory import Factory
|
from kivy.factory import Factory
|
||||||
@ -9,8 +7,7 @@ from appPublic.registerfunction import RegisterFunction
|
|||||||
|
|
||||||
def getUrlData(url, method='GET', params={}):
|
def getUrlData(url, method='GET', params={}):
|
||||||
blocks = Factory.Blocks()
|
blocks = Factory.Blocks()
|
||||||
d = blocks.getUrlData(url, method=method,
|
d = blocks.getUrlData(url, method=method, params=params)
|
||||||
params=params)
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
class DataGraber(EventDispatcher):
|
class DataGraber(EventDispatcher):
|
||||||
@ -141,7 +138,7 @@ class DataLoader(EventDispatcher):
|
|||||||
class UrlDataLoader(DataLoader):
|
class UrlDataLoader(DataLoader):
|
||||||
def load(self, *args, **kw):
|
def load(self, *args, **kw):
|
||||||
app = App.get_running_app()
|
app = App.get_running_app()
|
||||||
url = app.realurl(self.data_user.url)
|
url = self.data_user.url
|
||||||
method = self.data_user.method
|
method = self.data_user.method
|
||||||
params = self.data_user.params.copy()
|
params = self.data_user.params.copy()
|
||||||
params.update({
|
params.update({
|
||||||
@ -191,188 +188,3 @@ class RegisterFunctionDataLoader(DataLoader):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.dispatch('on_error', e)
|
self.dispatch('on_error', e)
|
||||||
|
|
||||||
|
|
||||||
=======
|
|
||||||
|
|
||||||
from kivy.event import EventDispatcher
|
|
||||||
from kivy.app import App
|
|
||||||
from kivy.factory import Factory
|
|
||||||
from .threadcall import HttpClient
|
|
||||||
from .utils import absurl
|
|
||||||
from appPublic.registerfunction import RegisterFunction
|
|
||||||
|
|
||||||
class DataGraber(EventDispatcher):
|
|
||||||
"""
|
|
||||||
Graber format
|
|
||||||
{
|
|
||||||
"widgettype":"DataGraber",
|
|
||||||
"options":{
|
|
||||||
"dataurl":"first",
|
|
||||||
"datarfname":"second",
|
|
||||||
"target":"third",
|
|
||||||
"params":
|
|
||||||
"method":
|
|
||||||
"pagging":"default false"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if dataurl present, the DataGraber using this dataurl to get and
|
|
||||||
return data
|
|
||||||
else if datarfname present, it find a registered function named
|
|
||||||
by 'datarfname' to return data
|
|
||||||
else if datatarget present, it find the widget and uses target
|
|
||||||
method(default is 'getValue') to return data
|
|
||||||
else it return None
|
|
||||||
"""
|
|
||||||
def __init__(self, **kw):
|
|
||||||
super().__init__()
|
|
||||||
self.options = kw
|
|
||||||
self.register_event_type('on_success')
|
|
||||||
self.register_event_type('on_error')
|
|
||||||
|
|
||||||
def load(self, *args, **kw):
|
|
||||||
ret = None
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
dataurl = self.options.get('dataurl')
|
|
||||||
if dataurl:
|
|
||||||
ret = self.loadUrlData(*args, **kw)
|
|
||||||
break
|
|
||||||
|
|
||||||
rfname = self.options.get('datarfname')
|
|
||||||
if rfname:
|
|
||||||
ret = self.loadRFData(*args, **kw)
|
|
||||||
break
|
|
||||||
target = self.options.get('datatarget')
|
|
||||||
if target:
|
|
||||||
ret = self.loadTargetData(*args, **kw)
|
|
||||||
break
|
|
||||||
except Exception as e:
|
|
||||||
self.dispatch('on_error', e)
|
|
||||||
return
|
|
||||||
if ret:
|
|
||||||
self.dispatch('on_success',ret)
|
|
||||||
else:
|
|
||||||
e = Exception('Not method to do load')
|
|
||||||
self.dispatch('on_error', e)
|
|
||||||
|
|
||||||
def loadUrlData(self, *args, **kw):
|
|
||||||
dataurl = self.options.get('dataurl')
|
|
||||||
hc = HttpClient()
|
|
||||||
params = self.options.get('params',{}).copy()
|
|
||||||
params.update(kw)
|
|
||||||
method = self.options.get('method','GET')
|
|
||||||
d = hc(dataurl, params=params,method=method)
|
|
||||||
return d
|
|
||||||
|
|
||||||
def loadRFData(self, *args, **kw):
|
|
||||||
rfname = self.options.get('datarfname')
|
|
||||||
rf = RegisterFunction()
|
|
||||||
f = rf.get(rfname)
|
|
||||||
if not f:
|
|
||||||
return None
|
|
||||||
params = self.options.get('params',{}).copy()
|
|
||||||
params.update(kw)
|
|
||||||
try:
|
|
||||||
d = f(**params)
|
|
||||||
return d
|
|
||||||
except Exception as e:
|
|
||||||
Logger.info('blocks : Exception:%s',e)
|
|
||||||
print_exc()
|
|
||||||
return None
|
|
||||||
|
|
||||||
def loadTargetData(self, *args, **kw):
|
|
||||||
target = self.options.get('datatarget')
|
|
||||||
w = Factory.Blocks.getWidgetById(target)
|
|
||||||
if not w:
|
|
||||||
return None
|
|
||||||
params = self.options.get('params',{}).copy()
|
|
||||||
params.update(kw)
|
|
||||||
method = params.get('method', 'getValue')
|
|
||||||
if not has(w, method):
|
|
||||||
return None
|
|
||||||
try:
|
|
||||||
f = getattr(w, method)
|
|
||||||
d = f()
|
|
||||||
return d
|
|
||||||
except Exception as e:
|
|
||||||
Logger.info('blocks : Exception %s', e)
|
|
||||||
print_exc()
|
|
||||||
return None
|
|
||||||
|
|
||||||
def on_success(self,d):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_error(self,e):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class DataLoader(EventDispatcher):
|
|
||||||
def __init__(self,data_user):
|
|
||||||
self.data_user = data_user
|
|
||||||
EventDispatcher.__init__(self)
|
|
||||||
self.register_event_type('on_success')
|
|
||||||
self.register_event_type('on_error')
|
|
||||||
|
|
||||||
def on_success(self,d):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_error(self,e):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def load(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class HttpDataLoader(DataLoader):
|
|
||||||
def load(self, *args, **kw):
|
|
||||||
app = App.get_running_app()
|
|
||||||
url = self.data_user.url
|
|
||||||
method = self.data_user.method
|
|
||||||
params = self.data_user.params.copy()
|
|
||||||
params.update({
|
|
||||||
"page":self.data_user.curpage,
|
|
||||||
"rows":self.data_user.page_rows
|
|
||||||
})
|
|
||||||
hc = HttpClient()
|
|
||||||
try:
|
|
||||||
r = hc(url, method=method, params=params)
|
|
||||||
self.dispatch('on_success', r)
|
|
||||||
return r
|
|
||||||
except Exception as e:
|
|
||||||
self.dispatch('on_error', e)
|
|
||||||
|
|
||||||
|
|
||||||
class ListDataLoader(DataLoader):
|
|
||||||
def load(self, *args, **kw):
|
|
||||||
p = self.data_user.curpage
|
|
||||||
r = self.data_user.page_rows
|
|
||||||
try:
|
|
||||||
s = self.data_user.data[(p-1)*r:p*r]
|
|
||||||
d = {
|
|
||||||
"total":len(self.data_user.data),
|
|
||||||
"rows":s
|
|
||||||
}
|
|
||||||
self.dispatch('on_success', d)
|
|
||||||
return d
|
|
||||||
except Exception as e:
|
|
||||||
self.dispatch('on_error', e)
|
|
||||||
|
|
||||||
class RegisterFunctionDataLoader(DataLoader):
|
|
||||||
def load(self, *args, **kw):
|
|
||||||
rf = RegisterFunction()
|
|
||||||
try:
|
|
||||||
rfname = self.data_user.rfname
|
|
||||||
func = rf.get(rfname)
|
|
||||||
if func is None:
|
|
||||||
raise Exception('%s is not a registerfunction' % rfname)
|
|
||||||
params = {k:v for k,v in self.user_data.params.items()}
|
|
||||||
params.update({
|
|
||||||
"page":self.data_user.curpage,
|
|
||||||
"rows":self.data_user.page_rows
|
|
||||||
})
|
|
||||||
s = func(**params)
|
|
||||||
self.dispatch('on_success', s)
|
|
||||||
return s
|
|
||||||
except Exception as e:
|
|
||||||
self.dispatch('on_error', e)
|
|
||||||
|
|
||||||
|
|
||||||
>>>>>>> cab6a2818466e5d32880a6a01e7afe16ad192675
|
|
||||||
|
107
kivyblocks/pyinterpreter.py
Normal file
107
kivyblocks/pyinterpreter.py
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
from traceback import print_exc
|
||||||
|
from io import StringIO
|
||||||
|
from contextlib import redirect_stdout
|
||||||
|
|
||||||
|
from kivy.app import App
|
||||||
|
from kivy.factory import Factory
|
||||||
|
from kivy.uix.boxlayout import BoxLayout
|
||||||
|
from kivy.uix.textinput import TextInput
|
||||||
|
|
||||||
|
from appPublic.Singleton import SingletonDecorator, GlobalEnv
|
||||||
|
|
||||||
|
from .baseWidget import PressableText
|
||||||
|
from .tab import TabsPanel
|
||||||
|
from .utils import *
|
||||||
|
from kivy.utils import platform
|
||||||
|
import plyer
|
||||||
|
if platform == 'android':
|
||||||
|
import android
|
||||||
|
import jnius
|
||||||
|
elif platform == 'ios':
|
||||||
|
from pyobjus import autoclass, protocol, objc_str
|
||||||
|
from pyobjus.dylib_manager import load_framework, INCLUDE
|
||||||
|
|
||||||
|
class PyInterpreter(TextInput):
|
||||||
|
def __init__(self, **kw):
|
||||||
|
kw['multiline'] = True
|
||||||
|
super().__init__(**kw)
|
||||||
|
self.env = {}
|
||||||
|
for n,f in Factory.classes.items():
|
||||||
|
if f['cls']:
|
||||||
|
self.env[n] = f['cls']
|
||||||
|
self.text = '>>>'
|
||||||
|
self.focus = True
|
||||||
|
self.scroll_line = -1
|
||||||
|
# self.bind(on_key_up=self.check_enter_key)
|
||||||
|
|
||||||
|
def find_line_start_idx(self):
|
||||||
|
lines = self.text.split('\n')
|
||||||
|
lines[-1] = '>>>'
|
||||||
|
txt = '\n'.join(lines)
|
||||||
|
idx = len(txt)
|
||||||
|
return idx
|
||||||
|
|
||||||
|
def keyboard_on_key_down(self, o, keycode, text, modifiers):
|
||||||
|
_, key = keycode
|
||||||
|
print('key=', key, 'pos=', self.cursor_pos, self.cursor_index())
|
||||||
|
script = None
|
||||||
|
if key == 'enter':
|
||||||
|
script = self.get_script()
|
||||||
|
if key == 'home':
|
||||||
|
stop_idx = self.find_line_start_idx()
|
||||||
|
self.cursor = self.get_cursor_from_index(stop_idx)
|
||||||
|
return
|
||||||
|
if key == 'left':
|
||||||
|
stop_idx = self.find_line_start_idx()
|
||||||
|
idx = self.cursor_index(cursor=self.cursor)
|
||||||
|
if idx <= stop_idx:
|
||||||
|
return
|
||||||
|
if key == 'up' or key == 'down':
|
||||||
|
self.scroll_script(key)
|
||||||
|
return
|
||||||
|
if key == 'backspace' and self.text[-3:] == '>>>':
|
||||||
|
return
|
||||||
|
ret = super().keyboard_on_key_down(o, keycode, text, modifiers)
|
||||||
|
if script:
|
||||||
|
self.exec_script(script)
|
||||||
|
elif key == 'enter':
|
||||||
|
self.text += '>>>'
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def scroll_script(self, key):
|
||||||
|
lines = self.text.split('\n')
|
||||||
|
slines = [l for l in lines if l.startswith('>>>') and l!='>>>']
|
||||||
|
maxl = len(slines) - 1
|
||||||
|
if self.scroll_line < 0:
|
||||||
|
self.scroll_line = maxl
|
||||||
|
if self.scroll_line == maxl and key == 'down':
|
||||||
|
return
|
||||||
|
if self.scroll_line == 0 and key == 'up':
|
||||||
|
return
|
||||||
|
if key == 'down':
|
||||||
|
self.scroll_line += 1
|
||||||
|
else:
|
||||||
|
self.scroll_line -= 1
|
||||||
|
lines[-1] = slines[self.scroll_line]
|
||||||
|
self.text = '\n'.join(lines)
|
||||||
|
|
||||||
|
def get_script(self):
|
||||||
|
ts = self.text.split('\n')
|
||||||
|
s = ts[-1][3:]
|
||||||
|
print('script=',s)
|
||||||
|
return s
|
||||||
|
|
||||||
|
def exec_script(self, script):
|
||||||
|
env = globals().copy()
|
||||||
|
f = StringIO()
|
||||||
|
with redirect_stdout(f):
|
||||||
|
try:
|
||||||
|
exec(script, env, self.env)
|
||||||
|
except Exception as e:
|
||||||
|
print('Exception:', e)
|
||||||
|
print_exc()
|
||||||
|
f.seek(0)
|
||||||
|
s = f.getvalue()
|
||||||
|
self.text = self.text + s + '\n>>>'
|
||||||
|
print('result=', s)
|
||||||
|
|
@ -43,10 +43,12 @@ from .hierarchy import Hierarchy
|
|||||||
from .price import PriceView
|
from .price import PriceView
|
||||||
from .ffpyplayer_video import FFVideo
|
from .ffpyplayer_video import FFVideo
|
||||||
from .upload import UploadFile
|
from .upload import UploadFile
|
||||||
|
from .pyinterpreter import PyInterpreter
|
||||||
|
|
||||||
r = Factory.register
|
r = Factory.register
|
||||||
# if kivy.platform in ['win','linux', 'macosx']:
|
# if kivy.platform in ['win','linux', 'macosx']:
|
||||||
# r('ScreenWithMic', ScreenWithMic)
|
# r('ScreenWithMic', ScreenWithMic)
|
||||||
|
r('PyInterpreter', PyInterpreter)
|
||||||
r('UploadFile', UploadFile)
|
r('UploadFile', UploadFile)
|
||||||
r('FFVideo', FFVideo)
|
r('FFVideo', FFVideo)
|
||||||
r('AnchorBox', AnchorBox)
|
r('AnchorBox', AnchorBox)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import codecs
|
||||||
import traceback
|
import traceback
|
||||||
try:
|
try:
|
||||||
import ujson as json
|
import ujson as json
|
||||||
@ -34,26 +35,29 @@ class Script:
|
|||||||
self.register('.ui', TemplateHandler)
|
self.register('.ui', TemplateHandler)
|
||||||
|
|
||||||
def url2filepath(self, url):
|
def url2filepath(self, url):
|
||||||
if url.startswith('file://'):
|
if url.startswith('file:///'):
|
||||||
url = url[7:]
|
url = url[8:]
|
||||||
return join(self.root, *url.split('/'))
|
ret = join(self.root, *url.split('/'))
|
||||||
|
# print('url2filepath():root=', self.root, url, ret)
|
||||||
|
return ret
|
||||||
|
|
||||||
def show_info(self, env):
|
def show_info(self, env):
|
||||||
workdir = env['workdir']
|
workdir = env['workdir']
|
||||||
sfile = env['filepath']
|
sfile = env['filepath']
|
||||||
url = env['url']
|
url = env['url']
|
||||||
print(f'script:workdir={workdir}')
|
# print(f'script:workdir={workdir}')
|
||||||
print(f'script:script_file={sfile}')
|
# print(f'script:script_file={sfile}')
|
||||||
print(f'script:url={url}')
|
# print(f'script:url={url}')
|
||||||
sdir = os.path.join(workdir, 'scripts')
|
sdir = os.path.join(workdir, 'scripts')
|
||||||
sf_exists = os.path.isdir(sdir)
|
sf_exists = os.path.isdir(sdir)
|
||||||
conf_f = os.path.join(workdir, 'conf', 'config.json')
|
conf_f = os.path.join(workdir, 'conf', 'config.json')
|
||||||
conf_exists = os.path.isfile(conf_f)
|
conf_exists = os.path.isfile(conf_f)
|
||||||
print(f'script:script exists {sf_exists}')
|
# print(f'script:script exists {sf_exists}')
|
||||||
print(f'script:config.json exists {conf_exists}')
|
# print(f'script:config.json exists {conf_exists}')
|
||||||
|
|
||||||
def dispatch(self, url, **kw):
|
def dispatch(self, url, **kw):
|
||||||
filepath = self.url2filepath(url)
|
filepath = self.url2filepath(url)
|
||||||
|
# print('dispatch():url=', url, 'filepath=', filepath)
|
||||||
for suffix, handler in self.handlers.items():
|
for suffix, handler in self.handlers.items():
|
||||||
if filepath.endswith(suffix):
|
if filepath.endswith(suffix):
|
||||||
env = self.env.copy()
|
env = self.env.copy()
|
||||||
@ -62,10 +66,6 @@ class Script:
|
|||||||
env['root_path'] = self.root
|
env['root_path'] = self.root
|
||||||
env['url'] = url
|
env['url'] = url
|
||||||
env['filepath'] = filepath
|
env['filepath'] = filepath
|
||||||
# print(f"workdir={env['workdir']}--------")
|
|
||||||
# if platform == 'android':
|
|
||||||
# self.show_info(env)
|
|
||||||
|
|
||||||
h = handler(env)
|
h = handler(env)
|
||||||
d = h.render()
|
d = h.render()
|
||||||
try:
|
try:
|
||||||
@ -92,7 +92,15 @@ class BaseHandler:
|
|||||||
return '/'.join(tokens)
|
return '/'.join(tokens)
|
||||||
|
|
||||||
p1 = self.env['url'].split('/')[:-1]
|
p1 = self.env['url'].split('/')[:-1]
|
||||||
return '/'.join(p1+tokens)
|
ret = '/'.join(p1+tokens)
|
||||||
|
"""
|
||||||
|
print('entire_url(): org_url=', self.env['url'],
|
||||||
|
'url=', url,
|
||||||
|
'p1=', p1,
|
||||||
|
'tokens=', tokens,
|
||||||
|
'ret=', ret)
|
||||||
|
"""
|
||||||
|
return ret
|
||||||
|
|
||||||
def __init__(self, env):
|
def __init__(self, env):
|
||||||
self.env = env
|
self.env = env
|
||||||
|
Loading…
Reference in New Issue
Block a user