kivyblocks/kivyblocks/script.py
2022-09-14 09:57:01 +08:00

150 lines
3.6 KiB
Python

import os
import traceback
try:
import ujson as json
except:
import json
from os.path import join, sep, dirname, basename
from appPublic.Singleton import GlobalEnv
from appPublic.jsonConfig import getConfig
from appPublic.myTE import MyTemplateEngine
from appPublic.Singleton import SingletonDecorator
from appPublic.dictObject import DictObject
from kivy.logger import Logger
from kivy.utils import platform
@SingletonDecorator
class ScriptEnv(DictObject):
pass
def set_script_env(n,v):
env = ScriptEnv()
env.update({n:v})
class Script:
def __init__(self, root):
self.root = root
self.env = {}
self.handlers = {}
self.register('.tmpl', TemplateHandler)
self.register('.dspy', DspyHandler)
self.register('.ui', TemplateHandler)
def url2filepath(self, url):
if url.startswith('file://'):
url = url[7:]
return join(self.root, *url.split('/'))
def show_info(self, env):
workdir = env['workdir']
sfile = env['filepath']
url = env['url']
print(f'script:workdir={workdir}')
print(f'script:script_file={sfile}')
print(f'script:url={url}')
sdir = os.path.join(workdir, 'scripts')
sf_exists = os.path.isdir(sdir)
conf_f = os.path.join(workdir, 'conf', 'config.json')
conf_exists = os.path.isfile(conf_f)
print(f'script:script exists {sf_exists}')
print(f'script:config.json exists {conf_exists}')
def dispatch(self, url, **kw):
filepath = self.url2filepath(url)
for suffix, handler in self.handlers.items():
if filepath.endswith(suffix):
env = self.env.copy()
env.update(ScriptEnv())
env.update(kw)
env['root_path'] = self.root
env['url'] = url
env['filepath'] = filepath
print(f'workdir={env['workdir']}--------')
if platform == 'android':
self.show_info(env)
h = handler(env)
d = h.render()
try:
return json.loads(d)
except:
return d
def register(self, suffix, handler):
self.handlers[suffix] = handler
def set_env(self, n, v):
self.env.update({n:v})
class BaseHandler:
def entire_url(self, url):
if url.startswith('file://') or \
url.startswith('http://') or \
url.startswith('hppts://'):
return url
tokens = url.split('/')
if tokens[0] == '':
root = self.env['root_path']
tokens[0] = root
return '/'.join(tokens)
p1 = self.env['url'].split('/')[:-1]
return '/'.join(p1+tokens)
def __init__(self, env):
self.env = env
self.env['entire_url'] = self.entire_url
class TemplateHandler(BaseHandler):
def __init__(self, env):
super().__init__(env)
root = env['root_path']
paths = [root]
fp = env['filepath'][len(root):]
plst = fp.split(sep)[:-1]
self.templ_file = basename(env['filepath'])
cpath = root
for p in plst:
cpath = join(cpath, p)
paths.append(cpath)
paths.reverse()
self.engine = MyTemplateEngine(paths)
def render(self):
try:
return self.engine.render(self.templ_file, self.env)
except Exception as e:
print('Exception:', str(e))
print('filename=', self.env['filepath'])
traceback.print_exc()
class DspyHandler(BaseHandler):
def __init__(self, env):
super().__init__(env)
def loadScript(self, path):
data = ''
with codecs.open(path,'rb','utf-8') as f:
data = f.read()
b= ''.join(data.split('\r'))
lines = b.split('\n')
lines = ['\t' + l for l in lines ]
txt = "def myfunc(request,**ns):\n" + '\n'.join(lines)
return txt
def render(self, params={}):
try:
lenv = self.env.copy()
lenv.update(params)
txt = self.loadScript(self.env['filepath'])
exec(txt,lenv,lenv)
func = lenv['myfunc']
return func(self.env, **lenv)
except Exception as e:
print('Exception:', str(e))
print('filename=', self.env['filepath'])
traceback.print_exc()