This commit is contained in:
yumoqing 2021-11-03 10:44:08 +08:00
parent aa94f34ea5
commit 2503a95fc4
2 changed files with 743 additions and 748 deletions

104
kivyblocks/blocks.py → kivyblocks/blocks.pyx Executable file → Normal file
View File

@ -1,7 +1,7 @@
import os import os
import sys import sys
import codecs import codecs
import json import ujson as json
from traceback import print_exc from traceback import print_exc
import kivy import kivy
@ -38,9 +38,6 @@ from .orientationlayout import OrientationLayout
from .threadcall import HttpClient from .threadcall import HttpClient
from .register import * from .register import *
def showError(e):
print('error',e)
class WidgetNotFoundById(Exception): class WidgetNotFoundById(Exception):
def __init__(self, id): def __init__(self, id):
super().__init__() super().__init__()
@ -94,7 +91,7 @@ class ArgumentError(Exception):
class NotRegistedWidget(Exception): class NotRegistedWidget(Exception):
def __init__(self,name): def __init__(self, name:str):
super().__init__() super().__init__()
self.widget_name = name self.widget_name = name
@ -105,7 +102,7 @@ class NotRegistedWidget(Exception):
def __expr__(self): def __expr__(self):
return self.__str__() return self.__str__()
def registerWidget(name,widget): def registerWidget(name:str,widget):
globals()[name] = widget globals()[name] = widget
@ -117,43 +114,22 @@ class Blocks(EventDispatcher):
self.register_event_type('on_failed') self.register_event_type('on_failed')
self.env = GlobalEnv() self.env = GlobalEnv()
def set(self,k,v): def set(self, k:str, v):
self.env[k] = v self.env[k] = v
def register_widget(self,name,widget): def register_widget(self, name:str, widget:Widget):
globals()[name] = widget globals()[name] = widget
def buildAction(self,widget,desc): def buildAction(self, widget:Widget, desc):
conform_desc = desc.get('conform') conform_desc = desc.get('conform')
blocks = Blocks() blocks = Blocks()
if not conform_desc: if not conform_desc:
return partial(blocks.uniaction, widget, desc) return partial(blocks.uniaction, widget, desc)
l = { func =partial(blocks.conform_action,widget, desc)
}
body="""def action(widget, *args, **kw):
jsonstr='''%s'''
desc = json.loads(jsonstr)
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()
print('Conform show.....')
""" % (json.dumps(desc))
exec(body,globals(),l)
f = l.get('action',None)
if f is None:
raise Exception('None Function')
func =partial(f,widget)
return func return func
def eval(self,s,l):
def eval(self, s:str, l:dict):
g = {} g = {}
forbidens = [ forbidens = [
"os", "os",
@ -166,14 +142,17 @@ class Blocks(EventDispatcher):
if k not in forbidens: if k not in forbidens:
g[k] = v g[k] = v
g['__builtins__'] = globals()['__builtins__'].copy() """
g['__builtins__'] = globals()['__builtins__']
g['__builtins__']['__import__'] = None g['__builtins__']['__import__'] = None
g['__builtins__']['__loader__'] = None g['__builtins__']['__loader__'] = None
g['__builtins__']['open'] = None g['__builtins__']['open'] = None
"""
g.update(self.env) g.update(self.env)
return eval(s,g,l) return eval(s,g,l)
def getUrlData(self,url,method='GET',params={}, files={}, def getUrlData(self, url:str, method:str='GET',
params:dict={}, files:dict={},
callback=None, callback=None,
errback=None,**kw): errback=None,**kw):
@ -220,7 +199,7 @@ class Blocks(EventDispatcher):
print_exc() print_exc()
return s return s
def arrayValueExpr(self,arr:list,localnamespace:dict={}): def arrayValueExpr(self,arr:list,localnamespace:dict={}) -> list:
d = [] d = []
for v in arr: for v in arr:
if type(v) == type(''): if type(v) == type(''):
@ -238,7 +217,7 @@ class Blocks(EventDispatcher):
d.append(v) d.append(v)
return d return d
def dictValueExpr(self,dic:dict,localnamespace:dict={}): def dictValueExpr(self,dic:dict,localnamespace:dict={}) -> dict:
d = {} d = {}
for k,v in dic.items(): for k,v in dic.items():
if type(v) == type(''): if type(v) == type(''):
@ -255,7 +234,7 @@ class Blocks(EventDispatcher):
continue continue
d[k] = v d[k] = v
return d return d
def valueExpr(self,obj,localnamespace={}): def valueExpr(self,obj,localnamespace:dict={}):
if type(obj) == type(''): if type(obj) == type(''):
return self.strValueExpr(obj,localnamespace) return self.strValueExpr(obj,localnamespace)
if type(obj) == type([]): if type(obj) == type([]):
@ -266,7 +245,7 @@ class Blocks(EventDispatcher):
return self.dictValueExpr(obj,localnamespace) return self.dictValueExpr(obj,localnamespace)
return obj return obj
def w_build(self,desc:dict): def w_build(self,desc) -> Widget:
# print('w_build(),desc=',desc) # print('w_build(),desc=',desc)
widgetClass = desc.get('widgettype',None) widgetClass = desc.get('widgettype',None)
if not widgetClass: if not widgetClass:
@ -305,7 +284,7 @@ class Blocks(EventDispatcher):
self.build_rest(widget,desc) self.build_rest(widget,desc)
return widget return widget
def build_attributes(self,widget,desc,t=None): def build_attributes(self, widget:Widget,desc,t=None):
excludes = ['widgettype','options','subwidgets','binds'] excludes = ['widgettype','options','subwidgets','binds']
for k,v in [(k,v) for k,v in desc.items() if k not in excludes]: 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'): if isinstance(v,dict) and v.get('widgettype'):
@ -322,10 +301,10 @@ class Blocks(EventDispatcher):
setattr(widget,k,self.valueExpr(v,\ setattr(widget,k,self.valueExpr(v,\
localnamespace={'self':widget})) localnamespace={'self':widget}))
def build_rest(self, widget,desc,t=None): def build_rest(self, widget:Widget,desc,t=None):
self.subwidget_total = len(desc.get('subwidgets',[])) self.subwidget_total = len(desc.get('subwidgets',[]))
self.subwidgets = [ None for i in range(self.subwidget_total)] self.subwidgets = [ None for i in range(self.subwidget_total)]
pos = 0 cdef int pos = 0
for pos,sw in enumerate(desc.get('subwidgets',[])): for pos,sw in enumerate(desc.get('subwidgets',[])):
b = Blocks() b = Blocks()
kw = self.valueExpr(sw.copy(), kw = self.valueExpr(sw.copy(),
@ -338,7 +317,7 @@ class Blocks(EventDispatcher):
localnamespace={'self':widget}) localnamespace={'self':widget})
self.buildBind(widget,kw) self.buildBind(widget,kw)
def buildBind(self,widget,desc): def buildBind(self, widget:Widget, desc):
wid = desc.get('wid','self') wid = desc.get('wid','self')
w = Blocks.getWidgetById(desc.get('wid','self'),from_widget=widget) w = Blocks.getWidgetById(desc.get('wid','self'),from_widget=widget)
if not w: if not w:
@ -356,7 +335,7 @@ class Blocks(EventDispatcher):
w.bind(**{event:f}) w.bind(**{event:f})
# Logger.info('Block: %s bind built', str(desc)) # Logger.info('Block: %s bind built', str(desc))
def multipleAction(self, widget, desc, *args): def multipleAction(self, widget:Widget, desc, *args):
desc1 = {k:v for k, v in desc.items() if k != 'actions'} desc1 = {k:v for k, v in desc.items() if k != 'actions'}
mydesc = desc1.copy() mydesc = desc1.copy()
for a in desc['actions']: for a in desc['actions']:
@ -364,7 +343,20 @@ class Blocks(EventDispatcher):
new_desc.update(a) new_desc.update(a)
self.uniaction(widget,new_desc, *args) self.uniaction(widget,new_desc, *args)
def uniaction(self,widget,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):
Logger.info('Block: uniaction() called, desc=%s', str(desc)) Logger.info('Block: uniaction() called, desc=%s', str(desc))
acttype = desc.get('actiontype') acttype = desc.get('actiontype')
@ -385,7 +377,7 @@ class Blocks(EventDispatcher):
alert("actiontype(%s) invalid" % acttype,title='error') alert("actiontype(%s) invalid" % acttype,title='error')
def eventAction(self, widget, desc, *args): def eventAction(self, widget:Widget, desc, *args):
target = self.get_target(widget, desc) target = self.get_target(widget, desc)
event = desc.get('dispatch_event') event = desc.get('dispatch_event')
if not event: if not event:
@ -403,12 +395,12 @@ class Blocks(EventDispatcher):
print_exc() print_exc()
return return
def get_target(self, widget, desc): def get_target(self, widget:Widget, desc):
if not desc.get('target'): if not desc.get('target'):
return None return None
return Blocks.getWidgetById(desc.get('target'),from_widget=widget) return Blocks.getWidgetById(desc.get('target'),from_widget=widget)
def blocksAction(self,widget,desc, *args): def blocksAction(self, widget:Widget, desc, *args):
target = self.get_target(widget, desc) target = self.get_target(widget, desc)
add_mode = desc.get('mode','replace') add_mode = desc.get('mode','replace')
opts = desc.get('options').copy() opts = desc.get('options').copy()
@ -417,7 +409,7 @@ class Blocks(EventDispatcher):
if d: if d:
p.update(d) p.update(d)
opts['options'] = p opts['options'] = p
def doit(target,add_mode,o,w): def doit(target:Widget, add_mode:str, o, w:Widget):
if target: if target:
if add_mode == 'replace': if add_mode == 'replace':
target.clear_widgets() target.clear_widgets()
@ -433,7 +425,7 @@ class Blocks(EventDispatcher):
b.bind(on_failed=doerr) b.bind(on_failed=doerr)
b.widgetBuild(opts) b.widgetBuild(opts)
def urlwidgetAction(self,widget,desc, *args): def urlwidgetAction(self, widget:Widget, desc, *args):
target = self.get_target(widget, desc) target = self.get_target(widget, desc)
add_mode = desc.get('mode','replace') add_mode = desc.get('mode','replace')
opts = desc.get('options').copy() opts = desc.get('options').copy()
@ -464,7 +456,7 @@ class Blocks(EventDispatcher):
b.bind(on_failed=doerr) b.bind(on_failed=doerr)
b.widgetBuild(d) b.widgetBuild(d)
def getActionData(self,widget,desc,*args): def getActionData(self, widget:Widget, desc,*args):
data = {} data = {}
rtdesc = self.build_rtdesc(desc) rtdesc = self.build_rtdesc(desc)
rt = self.get_rtdata(widget, rtdesc, *args) rt = self.get_rtdata(widget, rtdesc, *args)
@ -473,7 +465,7 @@ class Blocks(EventDispatcher):
data = keyMapping(data, desc.get('keymapping')) data = keyMapping(data, desc.get('keymapping'))
return data return data
def registedfunctionAction(self, widget, desc, *args): def registedfunctionAction(self, widget:Widget, desc, *args):
target = self.get_target(widget, desc) target = self.get_target(widget, desc)
rf = RegisterFunction() rf = RegisterFunction()
name = desc.get('rfname') name = desc.get('rfname')
@ -489,7 +481,7 @@ class Blocks(EventDispatcher):
params.update(d) params.update(d)
func(target, *args, **params) func(target, *args, **params)
def scriptAction(self, widget, desc, *args): def scriptAction(self, widget:Widget, desc, *args):
script = desc.get('script') script = desc.get('script')
if not script: if not script:
Logger.info('Block: scriptAction():desc(%s) target not found', Logger.info('Block: scriptAction():desc(%s) target not found',
@ -524,7 +516,7 @@ class Blocks(EventDispatcher):
return {} return {}
return rtdesc return rtdesc
def get_rtdata(self, widget, desc, *args): def get_rtdata(self, widget:Widget, desc, *args):
""" """
desc descript follow attributes desc descript follow attributes
{ {
@ -577,7 +569,7 @@ class Blocks(EventDispatcher):
print_exc() print_exc()
return {} return {}
def methodAction(self, widget, desc, *args): def methodAction(self, widget:Widget, desc, *args):
method = desc.get('method') method = desc.get('method')
target = self.get_target(widget, desc) target = self.get_target(widget, desc)
if target is None: if target is None:
@ -677,7 +669,7 @@ class Blocks(EventDispatcher):
return doit(desc) return doit(desc)
@classmethod @classmethod
def getWidgetById(self,id,from_widget=None): def getWidgetById(self, id:str, from_widget:Widget=None) -> Widget:
def find_widget_by_id(id, from_widget): def find_widget_by_id(id, from_widget):
if id=='self': if id=='self':
return from_widget return from_widget

View File

@ -3,6 +3,7 @@
from distutils.core import setup from distutils.core import setup
from setuptools import setup, find_packages from setuptools import setup, find_packages
from Cython.Build import cythonize
from version import version from version import version
# usage: # usage:
@ -32,6 +33,8 @@ package_data = {
setup( setup(
name="kivyblocks", name="kivyblocks",
ext_modules=cythonize(
['kivyblocks/blocks.pyx']),
version=version, version=version,
# uncomment the following lines if you fill them out in release.py # uncomment the following lines if you fill them out in release.py