diff --git a/.gitignore b/.gitignore index 2e9777372bd4eead102db1a21306fffb2e3ee2dd..07a441fbe19e202cfca1f885e327f3fbf936275f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,7 @@ -#以下文件不允许提交到git -__pycache__ -.settings -.buildpath -.project -*.log -*.pyc -*log/ /.idea /.vscode +*.log +.env /dist /kcweb.egg-info -/file -/utill/Queues -/utill/db/sqlitedata/kcwlicuxweb \ No newline at end of file +/build \ No newline at end of file diff --git a/README.md b/README.md index a926debd3e5c4705b93fdf3c95226a8ff08b14ae..558298cb7e9ffd279f5ed402ada366c9da209c51 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ +python -m build +twine upload dist/* -

kcweb==4.13.26框架简要说明

+

kcweb框架简要说明

kcweb作为web开发而设计的高性能框架,采用全新的架构思想,注重易用性。遵循MIT开源许可协议发布,意味着个人和企业可以免费使用kcweb,甚至允许把你基于kcweb开发的应用开源或商业产品发布或销售。 -[官方完整文档](https://intapp.kwebapp.cn/intapp/doc/index/finddoc/1/49/1 "官方文档") +[官方完整文档](https://intapp.kwebapp.cn/intapp/doc/index/finddoc/1/50/1 "官方文档") ------------ diff --git a/Events.py b/kcweb/Events.py similarity index 48% rename from Events.py rename to kcweb/Events.py index 1cba5fb57344ce80b8afe64190b1c19d94b8d682..a5420a0d51e707c73e8b226a661f50ccea58663d 100644 --- a/Events.py +++ b/kcweb/Events.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- -import os, sys, time, subprocess,signal +import os, time, subprocess,psutil from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler -eventgtimexz=0 class MyFileSystemEventHander(FileSystemEventHandler): + __eventgtimexz=0 def __init__(self, fn): super(MyFileSystemEventHander, self).__init__() self.restart = fn @@ -11,40 +11,54 @@ class MyFileSystemEventHander(FileSystemEventHandler): def on_any_event(self, event): if '.py' in event.src_path and event.src_path.endswith('.py'): global eventgtimexz - if time.time()-eventgtimexz > 3: - eventgtimexz=time.time() - # print('* 更新文件:%s' % event.src_path) - # time.sleep(10) - time.sleep(0.2) - self.restart() + if time.time()-self.__eventgtimexz > 0.5: + self.__eventgtimexz=time.time() + # print('* 更新文件:%s' % event.src_path,event.event_type) + if event.event_type=='modified': + if 'controller\__init__.py' in event.src_path or 'app\__init__.py' in event.src_path: + time.sleep(10) + pass + else: + self.restart() class Events: command = ['echo', 'ok'] process = None def __init__(self,argv): - if '--server' not in argv and 'python' not in argv[0] or 'kcw.py' in argv: - argv.insert(0, 'python') + # print('event1',argv) + # if ('--server' not in argv and 'python' not in argv[0]) or 'kcw.py' in argv: + # print('event2',argv) + # argv.insert(0, 'python') self.command = argv paths = os.path.abspath('.') - self.start_watch(paths, None) - + # print(paths) + self.start_watch(paths) + def kill_process(self): "关闭" if self.process: - self.process.kill() - self.process.wait() + if 'kcweb'==self.command[0] or 'kcwebplus'==self.command[0]: + try: + process = psutil.Process(self.process.pid) + except:pass + else: + for proc in process.children(recursive=True): + proc.kill() + proc.kill() + else: + self.process.kill() + self.process.wait() self.process = None - def start_process(self): "启动" - self.process = subprocess.Popen(self.command, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr) - + self.process = subprocess.Popen(self.command) def restart_process(self): "重启" + self.kill_process() time.sleep(0.1) self.start_process() - def start_watch(self,path, callback): + def start_watch(self,path): "执行" observer = Observer() observer.schedule(MyFileSystemEventHander(self.restart_process), path, recursive=True) @@ -53,7 +67,7 @@ class Events: try: while True: time.sleep(0.1) - except KeyboardInterrupt: + except KeyboardInterrupt as e: self.kill_process() # observer.stop() # observer.join() diff --git a/kcweb/LICENSE b/kcweb/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..e57e69a5be5508ee28532f589e3e30fb5eb69066 --- /dev/null +++ b/kcweb/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 冯树坤 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/__init__.py b/kcweb/__init__.py similarity index 100% rename from __init__.py rename to kcweb/__init__.py diff --git a/kcweb/__pycache__/Events.cpython-36.pyc b/kcweb/__pycache__/Events.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ccc76ffab75d8ed83f5660b71f32a0d596ebeb72 Binary files /dev/null and b/kcweb/__pycache__/Events.cpython-36.pyc differ diff --git a/kcweb/__pycache__/__init__.cpython-36.pyc b/kcweb/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47ed36b08747158cc0dcbe41e105bf80f7f8f897 Binary files /dev/null and b/kcweb/__pycache__/__init__.cpython-36.pyc differ diff --git a/kcweb/__pycache__/app.cpython-36.pyc b/kcweb/__pycache__/app.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0572d1852d8ccaca74f76f09d5847047854758af Binary files /dev/null and b/kcweb/__pycache__/app.cpython-36.pyc differ diff --git a/kcweb/__pycache__/kcweb.cpython-36.pyc b/kcweb/__pycache__/kcweb.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3cfcc3fd5c2a20f26f206a27679fb0f4304e320a Binary files /dev/null and b/kcweb/__pycache__/kcweb.cpython-36.pyc differ diff --git a/app.py b/kcweb/app.py similarity index 63% rename from app.py rename to kcweb/app.py index 3649151109d040b66de3215fef110e445206bd82..ce9d36d598420dfb569a96cff8413812648ab9bc 100644 --- a/app.py +++ b/kcweb/app.py @@ -1,24 +1,28 @@ # -*- coding: utf-8 -*- -import socket,time,re,os,sys,traceback,threading,urllib,cgi -from . Events import Events +import re,os,sys,traceback,threading,urllib,cgi +from wsgiref.simple_server import make_server from . common import * from . import config from mako.template import Template from datetime import datetime -from threading import local from .utill import filetype -from kcweb.utill.cache import cache as kcwcache -from wsgiref.simple_server import make_server -from kcweb.utill.db import mysql as kcwmysql -from kcweb.utill.db import sqlite as kcwsqlite +# import socket,time +# from threading import local +# from kcweb.utill.cache import cache as kcwcache +# from utill.db import mysql as kcwmysql +# from kcweb.utill.db import sqlite as kcwsqlite class web: __name=None __appname=None __config=config + __httpd=None def __new__(self,name,appname=None): self.__name=name self.__appname=appname - if self.__name != '__main__': + if self.__name == '__main__' or self.__name=='kcweb.kcweb' or self.__name=='kcwebplus.kcwebplus': + # print("web__new__",self.__name) + return super().__new__(self) + else: def apps(env, start_response): p=(config.app['staticpath']+env['RAW_URI'].replace(' ','')) status='200 ok' @@ -86,8 +90,9 @@ class web: start_response(status,resheader) return [body] return apps - else: - return super().__new__(self) + __host='' + __port='' + __filename='' def run(self,host="127.0.0.1",port="39001",name=None): """运行开发环境 @@ -95,78 +100,107 @@ class web: port: 端口 - name: python命令行解释机名字 + name: python命令行解释机名字 (该参数即将废弃) """ - if 'eventlog' in sys.argv or len(sys.argv)==1: - filename=sys.argv[0][:-3] + self.__host=host + self.__port=port + + cmd=sys.argv + config.app['cli']=False + if 'eventlog' in cmd or len(cmd)==1 or (len(cmd)>=2 and cmd[len(cmd)-1]=='server'): + # config.app['cli']=False + if 'kcwebplus' in cmd[0]: #基于新版本4.13.32之后 kcwebplus server运行 + cmd[0]='kcwebplus' + filename=cmd[0] + elif 'kcweb' in cmd[0]: #基于新版本4.13.32之后 kcweb server运行 + cmd[0]='kcweb' + filename=cmd[0] + else: #基于老版本4.13.32之前 python server.py运行 + filename=cmd[0][:-3] + self.__filename=filename if self.__config.app['app_debug']: - arg=sys.argv - if 'eventlog' in arg: + if 'eventlog' in cmd: self.__impl(host=host,port=port,filename=filename) else: if name: - arg.insert(0,name) - arg.append('eventlog') - Events(arg) + cmd.insert(0,name) + cmd.append('eventlog') + from . Events import Events + Events(cmd) else: - self.__impl( - host=host, - port=port, - filename=filename - ) + self.__impl(host=host,port=port,filename=filename) elif len(sys.argv)==3 and sys.argv[2]=='--cli': try: RAW_URI=sys.argv[1] except:pass else: - PATH_INFO=RAW_URI.split("?")[0] #/aa/bb/cc - if PATH_INFO[0]=='/': - PATH_INFO=PATH_INFO[1:] - QUERY_STRING=RAW_URI.replace(str(PATH_INFO),'').replace('?','') #a=1&b=1 - reqheader={ - 'REQUEST_METHOD':'GET', - 'RAW_URI':RAW_URI, - 'PATH_INFO':PATH_INFO, - 'QUERY_STRING':QUERY_STRING, - 'SERVER_PROTOCOL':'', - 'HTTP_HOST':'', - 'HTTP_COOKIE':'', - 'REMOTE_ADDR':'', - 'HTTP_X_REAL_IP':'', - 'HTTP_USER_AGENT':'', - 'BODY_DATA':'' - } - status,resheader,body=self.__routes(reqheader) - if 'body' not in body and 'html' not in body and '<' not in body and '>' not in body: - print(body) - exit() + self.cli(RAW_URI) + def cli(self,RAW_URI): + config.app['cli']=True + if RAW_URI: + PATH_INFO=RAW_URI.split("?")[0] #/aa/bb/cc + if PATH_INFO[0]=='/': + PATH_INFO=PATH_INFO[1:] + else: + PATH_INFO=RAW_URI + clipidpath=get_folder()+"/pid/"+md5(RAW_URI)+"_cli_pid" + pid='' + if(config.app['save_cli_pid']): + kill_route_cli(RAW_URI) + save_route_cli_pid(RAW_URI) + QUERY_STRING=RAW_URI.replace(str(PATH_INFO),'').replace('?','') #a=1&b=1 + reqheader={ + 'REQUEST_METHOD':'GET', + 'RAW_URI':RAW_URI, + 'PATH_INFO':PATH_INFO, + 'QUERY_STRING':QUERY_STRING, + 'SERVER_PROTOCOL':'', + 'HTTP_HOST':'', + 'HTTP_COOKIE':'', + 'REMOTE_ADDR':'', + 'HTTP_X_REAL_IP':'', + 'HTTP_USER_AGENT':'', + 'BODY_DATA':'' + } + status,resheader,body=self.__routes(reqheader) + print(body) + if(config.app['save_cli_pid']) and pid: + + try: + os.remove(clipidpath) + except:pass def __impl(self,host,port,filename): "运行测试服务器" try: - if config.app['http_server']=='wsgiref': - self.__http_wsgi( - host=host, - port=port, - filename=filename - ) - elif config.app['http_server']=='kcweb': - self.__http_sever( - host=host, - port=port, - filename=filename - ) - elif config.app['http_server']=='kcweb_server': - self.__http_server( - host=host, - port=port, - filename=filename - ) - else: - self.__http_wsgi( - host=host, - port=port, - filename=filename - ) + # if config.app['http_server']=='wsgiref': + # self.__http_wsgi( + # host=host, + # port=port, + # filename=filename + # ) + # elif config.app['http_server']=='kcweb': + # self.__http_sever( + # host=host, + # port=port, + # filename=filename + # ) + # elif config.app['http_server']=='kcweb_server': + # self.__http_server( + # host=host, + # port=port, + # filename=filename + # ) + # else: + # self.__http_wsgi( + # host=host, + # port=port, + # filename=filename + # ) + self.__http_wsgi( + host=host, + port=port, + filename=filename + ) except KeyboardInterrupt: pass @@ -391,9 +425,9 @@ class web: except: globals.HEADER.HTTP_USER_AGENT=None def __del_globals(): - globals.VAR = local() - globals.HEADER = local() - globals.G = local() + globals.VAR = threading.local() + globals.HEADER = threading.local() + globals.G = threading.local() def __routes(self,header): body="这是一个http测试服务器" status="200 ok" @@ -529,7 +563,12 @@ class web: data=errms,e=e ) if not data: - data=getattr(obj,funct)(*param) + try: + objclass=getattr(obj,files) #新增 + except: + data=getattr(obj,funct)(*param) #兼容性之前的控制器 + else: + data=getattr(objclass,funct)(*param) body,status,resheader=web.__tran( self,data, status, @@ -739,249 +778,254 @@ class web: body=bytes(body, encoding='utf-8') start_response(status,resheader) return [body] + def __http_wsgi(self,host,port,filename): "http——wsgi测试服务" print("* \033[1;31;40m! 警告:\033[0m这是一个wsgiref开发服务器。不要在生产环境中部署使用它") - print('* 生产环境中建议使用gunicorn,gunicorn运行命令如:gunicorn -b '+host+':'+str(port)+' '+str(filename)+':app') - if self.__config.app['app_debug']: - print('* 调试器:开启') + # print('* 生产环境中建议使用gunicorn,gunicorn运行命令如:gunicorn -b '+host+':'+str(port)+' '+str(filename)+':app') + if host=='0.0.0.0': + print("\033[32m* (CTRL+单击打开)http://127.0.0.1:"+str(port)+"(按CTRL+C退出)") else: - print('* 调试器:已关闭') - print("* 运行在http://"+host+":"+str(port)+"/ (按CTRL+C退出)") - httpd = make_server(host, int(port), self.__application) - httpd.serve_forever() - def __http_server(self,host,port,filename): - "http测试服务" - tcp_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM) - try: - tcp_socket.bind((host,int(port))) - except OSError: - print("通常每个套接字地址(协议/网络地址/端口)只允许使用一次(按CTRL+C退出)") + print("\033[32m* 运行在http://"+host+":"+str(port)+"(按CTRL+C退出)") + if self.__config.app['app_debug']: + print('\033[37m* 调试器:开启') else: - tcp_socket.listen(1024) - print('! \033[1;31;40m警告:\033[0m这是一个kcweb_server开发服务器。不要在生产环境中部署使用它') - print('* 生产环境中建议使用gunicorn,gunicorn运行命令如:gunicorn -b '+host+':'+str(port)+' '+str(filename)+':app') - if self.__config.app['app_debug']: - print('* 调试器:开启') - else: - print('* 调试器:已关闭') - print("* 运行在http://"+host+":"+str(port)+"/ (按CTRL+C退出)") - while True: - new_tcp_socket,client_info=tcp_socket.accept() - t=threading.Thread(target=self.__server_client,args=(new_tcp_socket,)) - t.daemon=True - t.start() - tcp_socket.close() - def __server_client(self,new_socket): - # 处理http的的请求 - data=new_socket.recv(1047576).decode() - if data: - datas=data.split("\r\n") - data1=datas[0] - #reqsest - REQUEST_METHOD=data1.split("/")[0].replace(' ','') ##GET - RAW_URI=re.findall(REQUEST_METHOD+"(.+?) HTTP", data1) #/aa/bb/cc?a=1&b=1 - if RAW_URI: - RAW_URI=RAW_URI[0] - else: - RAW_URI='' - PATH_INFO=RAW_URI.split("?")[0] #/aa/bb/cc - QUERY_STRING=RAW_URI.replace(str(PATH_INFO),'').replace('?','') #a=1&b=1 - SERVER_PROTOCOL=data1.split(" ")[-1] #HTTP/1.1 - HTTP_HOST=re.findall("Host: (.+?)\r\n", data)#212.129.149.238:39010 - if HTTP_HOST: - HTTP_HOST=HTTP_HOST[0] - else: - HTTP_HOST='' - HTTP_COOKIE=re.findall("Cookie: (.+?)\r\n", data)#cookie - if HTTP_COOKIE: - HTTP_COOKIE=HTTP_COOKIE[0] - else: - HTTP_COOKIE='' - REMOTE_ADDR='' - HTTP_USER_AGENT=re.findall("User-Agent: (.+?)\r\n", data) #Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0 - if HTTP_USER_AGENT: - HTTP_USER_AGENT=HTTP_USER_AGENT[0] - else: - HTTP_USER_AGENT='' - BODY_DATA=datas[len(datas)-1] - # print(data) - #reqsest - reqheader={ - 'REQUEST_METHOD':REQUEST_METHOD, - 'RAW_URI':RAW_URI, - 'PATH_INFO':PATH_INFO, - 'QUERY_STRING':QUERY_STRING, - 'SERVER_PROTOCOL':SERVER_PROTOCOL, - 'HTTP_HOST':HTTP_HOST, - 'HTTP_COOKIE':HTTP_COOKIE, - 'REMOTE_ADDR':REMOTE_ADDR, - 'HTTP_X_REAL_IP':'', - 'HTTP_USER_AGENT':HTTP_USER_AGENT, - 'BODY_DATA':BODY_DATA - } - p=(config.app['staticpath']+RAW_URI.replace(' ','')) - # print("目录",p) - status='200 ok' - if os.path.isfile(p): - # print('静态文件',p) - kind = filetype.guess(p) - if kind is None: + print('\033[37m* 调试器:已关闭') + self.__httpd = make_server(host, int(port), self.__application) + self.__httpd.serve_forever() + # def __server_client(self,new_socket): + # # 处理http的的请求 + # data=new_socket.recv(1047576).decode() + # if data: + # datas=data.split("\r\n") + # data1=datas[0] + # #reqsest + # REQUEST_METHOD=data1.split("/")[0].replace(' ','') ##GET + # RAW_URI=re.findall(REQUEST_METHOD+"(.+?) HTTP", data1) #/aa/bb/cc?a=1&b=1 + # if RAW_URI: + # RAW_URI=RAW_URI[0] + # else: + # RAW_URI='' + # PATH_INFO=RAW_URI.split("?")[0] #/aa/bb/cc + # QUERY_STRING=RAW_URI.replace(str(PATH_INFO),'').replace('?','') #a=1&b=1 + # SERVER_PROTOCOL=data1.split(" ")[-1] #HTTP/1.1 + # HTTP_HOST=re.findall("Host: (.+?)\r\n", data)#212.129.149.238:39010 + # if HTTP_HOST: + # HTTP_HOST=HTTP_HOST[0] + # else: + # HTTP_HOST='' + # HTTP_COOKIE=re.findall("Cookie: (.+?)\r\n", data)#cookie + # if HTTP_COOKIE: + # HTTP_COOKIE=HTTP_COOKIE[0] + # else: + # HTTP_COOKIE='' + # REMOTE_ADDR='' + # HTTP_USER_AGENT=re.findall("User-Agent: (.+?)\r\n", data) #Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0 + # if HTTP_USER_AGENT: + # HTTP_USER_AGENT=HTTP_USER_AGENT[0] + # else: + # HTTP_USER_AGENT='' + # BODY_DATA=datas[len(datas)-1] + # # print(data) + # #reqsest + # reqheader={ + # 'REQUEST_METHOD':REQUEST_METHOD, + # 'RAW_URI':RAW_URI, + # 'PATH_INFO':PATH_INFO, + # 'QUERY_STRING':QUERY_STRING, + # 'SERVER_PROTOCOL':SERVER_PROTOCOL, + # 'HTTP_HOST':HTTP_HOST, + # 'HTTP_COOKIE':HTTP_COOKIE, + # 'REMOTE_ADDR':REMOTE_ADDR, + # 'HTTP_X_REAL_IP':'', + # 'HTTP_USER_AGENT':HTTP_USER_AGENT, + # 'BODY_DATA':BODY_DATA + # } + # p=(config.app['staticpath']+RAW_URI.replace(' ','')) + # # print("目录",p) + # status='200 ok' + # if os.path.isfile(p): + # # print('静态文件',p) + # kind = filetype.guess(p) + # if kind is None: - f=open(p,"rb") - body=f.read() - f.close() - resheader=[("Cache-Control","public, max-age=43200"),("Expires","Thu, 07 Nov 2019 02:59:02 GMT")] + # f=open(p,"rb") + # body=f.read() + # f.close() + # resheader=[("Cache-Control","public, max-age=43200"),("Expires","Thu, 07 Nov 2019 02:59:02 GMT")] - header="HTTP/1.1 %s \n" % status - header+="Content-Length:%d\n" % len(body) - else: - f=open(p,"rb") - body=f.read() - f.close() - resheader=[("Content-Type",kind.mime),("Cache-Control","public, max-age=43200"),("Accept-Ranges","bytes"),("Expires","Thu, 07 Nov 2019 02:59:02 GMT")] - header="HTTP/1.1 %s \n" % status - header+="Content-Length:%d\n" % len(body) - else: - status,resheader,body=self.__routes(reqheader) - if type(body) is bytes: - pass - else: - body=body.encode() - header="HTTP/1.1 %s \n" % status - header+="Content-Length:%d\n" % len(body) + # header="HTTP/1.1 %s \n" % status + # header+="Content-Length:%d\n" % len(body) + # else: + # f=open(p,"rb") + # body=f.read() + # f.close() + # resheader=[("Content-Type",kind.mime),("Cache-Control","public, max-age=43200"),("Accept-Ranges","bytes"),("Expires","Thu, 07 Nov 2019 02:59:02 GMT")] + # header="HTTP/1.1 %s \n" % status + # header+="Content-Length:%d\n" % len(body) + # else: + # status,resheader,body=self.__routes(reqheader) + # if type(body) is bytes: + # pass + # else: + # body=body.encode() + # header="HTTP/1.1 %s \n" % status + # header+="Content-Length:%d\n" % len(body) - print(HTTP_HOST+' -- ['+str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))+'] "'+REQUEST_METHOD+" "+RAW_URI +" "+SERVER_PROTOCOL + '" '+status+"-") - t=time.time() - header+="Server:kcweb"+str(config.kcweb['version'])+"\n" - header+="Date:%s\n" % datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') - for t in resheader: - header+="%s:%s\n" % (t[0],t[1]) - header+="\n" - try: - new_socket.send(header.encode()) - new_socket.send(body) - except Exception as e: - pass - new_socket.close() - def __http_sever(self,host,port,filename): - #http测试服务器 - print('\033[1;31;40m! 警告:\033[0m这是一个kcweb开发服务器。不要在生产环境中部署使用它') - print('* 生产环境中建议使用gunicorn,gunicorn运行命令如:gunicorn -b '+host+':'+str(port)+' '+str(filename)+':app') - if self.__config.app['app_debug']: - print('* 调试器:开启') - else: - print('* 调试器:已关闭') - print("* 运行在http://"+host+":"+str(port)+"/ (按CTRL+C退出)") - tcp_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM) - tcp_socket.bind((host,int(port))) - tcp_socket.listen(1024) - pack_length=1024 - tcp_socket.setblocking(False) - tcp_socket_list=list() - while True: - try: - new_tcp_socket,client_info=tcp_socket.accept() - except: - pass - else: - new_tcp_socket.setblocking(False) - tcp_socket_list.append(new_tcp_socket) - for cli_soc in tcp_socket_list: - try: - data=cli_soc.recv(pack_length).decode() - except Exception as e: - pass - else: - if data: - datas=data.split("\r\n") - data1=datas[0] - #reqsest - REQUEST_METHOD=data1.split("/")[0].replace(' ','') ##GET - RAW_URI=re.findall(REQUEST_METHOD+"(.+?) HTTP", data1) #/aa/bb/cc?a=1&b=1 - if RAW_URI: - RAW_URI=RAW_URI[0] - else: - RAW_URI='' - PATH_INFO=RAW_URI.split("?")[0] #/aa/bb/cc - QUERY_STRING=RAW_URI.replace(str(PATH_INFO),'').replace('?','') #a=1&b=1 - SERVER_PROTOCOL=data1.split(" ")[-1] #HTTP/1.1 - HTTP_HOST=re.findall("Host: (.+?)\r\n", data)#212.129.149.238:39010 - if HTTP_HOST: - HTTP_HOST=HTTP_HOST[0] - else: - HTTP_HOST='' - HTTP_COOKIE=re.findall("Cookie: (.+?)\r\n", data)#cookie - if HTTP_COOKIE: - HTTP_COOKIE=HTTP_COOKIE[0] - else: - HTTP_COOKIE='' - REMOTE_ADDR='' - HTTP_USER_AGENT=re.findall("User-Agent: (.+?)\r\n", data) #Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0 - if HTTP_USER_AGENT: - HTTP_USER_AGENT=HTTP_USER_AGENT[0] - else: - HTTP_USER_AGENT='' - BODY_DATA=datas[len(datas)-1] - # print(data) - #reqsest - reqheader={ - 'REQUEST_METHOD':REQUEST_METHOD, - 'RAW_URI':RAW_URI, - 'PATH_INFO':PATH_INFO, - 'QUERY_STRING':QUERY_STRING, - 'SERVER_PROTOCOL':SERVER_PROTOCOL, - 'HTTP_HOST':HTTP_HOST, - 'HTTP_COOKIE':HTTP_COOKIE, - 'REMOTE_ADDR':REMOTE_ADDR, - 'HTTP_X_REAL_IP':'', - 'HTTP_USER_AGENT':HTTP_USER_AGENT, - 'BODY_DATA':BODY_DATA - } - p=(config.app['staticpath']+RAW_URI.replace(' ','')) - # print("目录",p) - status='200 ok' - if os.path.isfile(p): - # print('静态文件',p) - kind = filetype.guess(p) - if kind is None: + # print(HTTP_HOST+' -- ['+str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))+'] "'+REQUEST_METHOD+" "+RAW_URI +" "+SERVER_PROTOCOL + '" '+status+"-") + # t=time.time() + # header+="Server:kcweb"+str(config.kcweb['version'])+"\n" + # header+="Date:%s\n" % datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') + # for t in resheader: + # header+="%s:%s\n" % (t[0],t[1]) + # header+="\n" + # try: + # new_socket.send(header.encode()) + # new_socket.send(body) + # except Exception as e: + # pass + # new_socket.close() + # def __http_server(self,host,port,filename): + # "http测试服务" + # tcp_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM) + # try: + # tcp_socket.bind((host,int(port))) + # except OSError: + # print("通常每个套接字地址(协议/网络地址/端口)只允许使用一次(按CTRL+C退出)") + # else: + # tcp_socket.listen(1024) + # print('! \033[1;31;40m警告:\033[0m这是一个kcweb_server开发服务器。不要在生产环境中部署使用它') + # print('* 生产环境中建议使用gunicorn,gunicorn运行命令如:gunicorn -b '+host+':'+str(port)+' '+str(filename)+':app') + # if self.__config.app['app_debug']: + # print('* 调试器:开启') + # else: + # print('* 调试器:已关闭') + # print("* 运行在http://"+host+":"+str(port)+"/ (按CTRL+C退出)") + # while True: + # new_tcp_socket,client_info=tcp_socket.accept() + # t=threading.Thread(target=self.__server_client,args=(new_tcp_socket,)) + # t.daemon=True + # t.start() + # tcp_socket.close() + + # def __http_sever(self,host,port,filename): + # #http测试服务器 + # print('\033[1;31;40m! 警告:\033[0m这是一个kcweb开发服务器。不要在生产环境中部署使用它') + # print('* 生产环境中建议使用gunicorn,gunicorn运行命令如:gunicorn -b '+host+':'+str(port)+' '+str(filename)+':app') + # if self.__config.app['app_debug']: + # print('* 调试器:开启') + # else: + # print('* 调试器:已关闭') + # print("* 运行在http://"+host+":"+str(port)+"/ (按CTRL+C退出)") + # tcp_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM) + # tcp_socket.bind((host,int(port))) + # tcp_socket.listen(1024) + # pack_length=1024 + # tcp_socket.setblocking(False) + # tcp_socket_list=list() + # while True: + # try: + # new_tcp_socket,client_info=tcp_socket.accept() + # except: + # pass + # else: + # new_tcp_socket.setblocking(False) + # tcp_socket_list.append(new_tcp_socket) + # for cli_soc in tcp_socket_list: + # try: + # data=cli_soc.recv(pack_length).decode() + # except Exception as e: + # pass + # else: + # if data: + # datas=data.split("\r\n") + # data1=datas[0] + # #reqsest + # REQUEST_METHOD=data1.split("/")[0].replace(' ','') ##GET + # RAW_URI=re.findall(REQUEST_METHOD+"(.+?) HTTP", data1) #/aa/bb/cc?a=1&b=1 + # if RAW_URI: + # RAW_URI=RAW_URI[0] + # else: + # RAW_URI='' + # PATH_INFO=RAW_URI.split("?")[0] #/aa/bb/cc + # QUERY_STRING=RAW_URI.replace(str(PATH_INFO),'').replace('?','') #a=1&b=1 + # SERVER_PROTOCOL=data1.split(" ")[-1] #HTTP/1.1 + # HTTP_HOST=re.findall("Host: (.+?)\r\n", data)#212.129.149.238:39010 + # if HTTP_HOST: + # HTTP_HOST=HTTP_HOST[0] + # else: + # HTTP_HOST='' + # HTTP_COOKIE=re.findall("Cookie: (.+?)\r\n", data)#cookie + # if HTTP_COOKIE: + # HTTP_COOKIE=HTTP_COOKIE[0] + # else: + # HTTP_COOKIE='' + # REMOTE_ADDR='' + # HTTP_USER_AGENT=re.findall("User-Agent: (.+?)\r\n", data) #Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0 + # if HTTP_USER_AGENT: + # HTTP_USER_AGENT=HTTP_USER_AGENT[0] + # else: + # HTTP_USER_AGENT='' + # BODY_DATA=datas[len(datas)-1] + # # print(data) + # #reqsest + # reqheader={ + # 'REQUEST_METHOD':REQUEST_METHOD, + # 'RAW_URI':RAW_URI, + # 'PATH_INFO':PATH_INFO, + # 'QUERY_STRING':QUERY_STRING, + # 'SERVER_PROTOCOL':SERVER_PROTOCOL, + # 'HTTP_HOST':HTTP_HOST, + # 'HTTP_COOKIE':HTTP_COOKIE, + # 'REMOTE_ADDR':REMOTE_ADDR, + # 'HTTP_X_REAL_IP':'', + # 'HTTP_USER_AGENT':HTTP_USER_AGENT, + # 'BODY_DATA':BODY_DATA + # } + # p=(config.app['staticpath']+RAW_URI.replace(' ','')) + # # print("目录",p) + # status='200 ok' + # if os.path.isfile(p): + # # print('静态文件',p) + # kind = filetype.guess(p) + # if kind is None: - f=open(p,"rb") - body=f.read() - f.close() - resheader=[("Cache-Control","public, max-age=43200"),("Expires","Thu, 07 Nov 2019 02:59:02 GMT")] + # f=open(p,"rb") + # body=f.read() + # f.close() + # resheader=[("Cache-Control","public, max-age=43200"),("Expires","Thu, 07 Nov 2019 02:59:02 GMT")] - header="HTTP/1.1 %s \n" % status - header+="Content-Length:%d\n" % len(body) - else: - f=open(p,"rb") - body=f.read() - f.close() - resheader=[("Content-Type",kind.mime),("Cache-Control","public, max-age=43200"),("Accept-Ranges","bytes"),("Expires","Thu, 07 Nov 2019 02:59:02 GMT")] - header="HTTP/1.1 %s \n" % status - header+="Content-Length:%d\n" % len(body) - else: - status,resheader,body=self.__routes(reqheader) - if type(body) is bytes: - pass - else: - body=body.encode() - header="HTTP/1.1 %s \n" % status - header+="Content-Length:%d\n" % len(body) + # header="HTTP/1.1 %s \n" % status + # header+="Content-Length:%d\n" % len(body) + # else: + # f=open(p,"rb") + # body=f.read() + # f.close() + # resheader=[("Content-Type",kind.mime),("Cache-Control","public, max-age=43200"),("Accept-Ranges","bytes"),("Expires","Thu, 07 Nov 2019 02:59:02 GMT")] + # header="HTTP/1.1 %s \n" % status + # header+="Content-Length:%d\n" % len(body) + # else: + # status,resheader,body=self.__routes(reqheader) + # if type(body) is bytes: + # pass + # else: + # body=body.encode() + # header="HTTP/1.1 %s \n" % status + # header+="Content-Length:%d\n" % len(body) - print(HTTP_HOST+' -- ['+str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))+'] "'+REQUEST_METHOD+" "+RAW_URI +" "+SERVER_PROTOCOL + '" '+status+"-") - t=time.time() - header+="Server:kcweb"+str(config.kcweb['version'])+"\n" - header+="Date:%s\n" % datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') - for t in resheader: - header+="%s:%s\n" % (t[0],t[1]) - header+="\n" - try: - cli_soc.send(header.encode()) - cli_soc.send(body) - except Exception as e: - cli_soc.close() - else: - cli_soc.close() - tcp_socket_list.remove(cli_soc) - tcp_socket.close() + # print(HTTP_HOST+' -- ['+str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))+'] "'+REQUEST_METHOD+" "+RAW_URI +" "+SERVER_PROTOCOL + '" '+status+"-") + # t=time.time() + # header+="Server:kcweb"+str(config.kcweb['version'])+"\n" + # header+="Date:%s\n" % datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') + # for t in resheader: + # header+="%s:%s\n" % (t[0],t[1]) + # header+="\n" + # try: + # cli_soc.send(header.encode()) + # cli_soc.send(body) + # except Exception as e: + # cli_soc.close() + # else: + # cli_soc.close() + # tcp_socket_list.remove(cli_soc) + # tcp_socket.close() diff --git a/common/__init__.py b/kcweb/common/__init__.py similarity index 100% rename from common/__init__.py rename to kcweb/common/__init__.py diff --git a/kcweb/common/__pycache__/__init__.cpython-36.pyc b/kcweb/common/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa2ee76e3aac1ca93d76c11b74c79cb50b7d8163 Binary files /dev/null and b/kcweb/common/__pycache__/__init__.cpython-36.pyc differ diff --git a/kcweb/common/__pycache__/autoload.cpython-36.pyc b/kcweb/common/__pycache__/autoload.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..951e3c07e85596f7c3bacd4ec7e8d1b7b902417b Binary files /dev/null and b/kcweb/common/__pycache__/autoload.cpython-36.pyc differ diff --git a/kcweb/common/__pycache__/globals.cpython-36.pyc b/kcweb/common/__pycache__/globals.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2bcada23753f4c5f2ee903809d193a387a0f3d48 Binary files /dev/null and b/kcweb/common/__pycache__/globals.cpython-36.pyc differ diff --git a/kcweb/common/__pycache__/request.cpython-36.pyc b/kcweb/common/__pycache__/request.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..02f189ef27bad70aeef88cdc5f923f795469b7a6 Binary files /dev/null and b/kcweb/common/__pycache__/request.cpython-36.pyc differ diff --git a/kcweb/common/__pycache__/session.cpython-36.pyc b/kcweb/common/__pycache__/session.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..acf2773e0498a19e5d167cd38dafbdc247663d2a Binary files /dev/null and b/kcweb/common/__pycache__/session.cpython-36.pyc differ diff --git a/common/autoload.py b/kcweb/common/autoload.py similarity index 66% rename from common/autoload.py rename to kcweb/common/autoload.py index fb16645905830b41d5dfb5bb2503839b981daf89..e3d078c6e56bc0d6b22e5dbbf4d5bd78c23578b4 100644 --- a/common/autoload.py +++ b/kcweb/common/autoload.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -import time,hashlib,json,re,os,platform,sys,shutil,requests,importlib,traceback,pip,gzip,tarfile,zipfile,random,copy +import time,hashlib,json,re,os,platform,sys,shutil,requests,importlib,traceback,pip,gzip,tarfile,zipfile,random,copy,chardet import datetime as core_datetime from kcweb import config from kcweb.utill.dateutil.relativedelta import relativedelta as core_relativedelta @@ -18,8 +18,11 @@ from email.mime.text import MIMEText from email.utils import formataddr from kcweb.utill import filetype from . import globals - -import asyncio,websockets,urllib,threading +import asyncio,websockets,urllib,threading,psutil,signal +python_version=platform.python_version() +if python_version[0:3]!='3.8': + print("\033[1;31;40m "+config.kcweb['name']+"-"+config.kcweb['version']+"依赖python3.8,与你现在的python"+python_version+"不兼容,推荐安装python3.8") + exit() class kcwebsocket: "websocket服务端" __clientlists=[] #所有客户端绑定的对象 @@ -162,6 +165,18 @@ class kcwebsocket: return int 返回一个数字 """ return len(self.__lists) + def getGroupCount(self): + """获取组数量 + + return int 返回一个数字 + """ + return len(self.__group) + def getGroupname(self): + """获取组名称 + + return list 返回一列表 + """ + return list(self.__group) async def send_all(self,message): "给所有人发送消息,包括自己" for l in self.__clientlists: @@ -184,30 +199,39 @@ class kcwebsocket: await self.send_client(clientid,recv_text) #给当前用户发送消息 async def onClose(self,clientid): "客户端与websocket的连接断开时触发" + await self.CloseSocket(self,clientid) if config.app['app_debug']: print("onClose",clientid) - async def __onClose(self,clientid): - xb=self.__lists.index(clientid) - del self.__lists[xb] - del self.__clientlists[xb] - if self.__uid: - for uid in self.__uid.keys(): - try: - self.__uid[uid] - except KeyError: - pass - else: + async def CloseSocket(self,clientid): + "关闭当前客户端socket" + try: + xb=self.__lists.index(clientid) + except:pass + else: + del self.__lists[xb] + websockets=self.__clientlists[xb]['socket'] + del self.__clientlists[xb] + if self.__uid: + for uid in self.__uid.keys(): try: - self.__uid[uid]['clientid'] + self.__uid[uid] except KeyError: pass else: - self.__uid[uid].remove(clientid) + try: + self.__uid[uid]['clientid'] + except KeyError: + pass + else: + self.__uid[uid].remove(clientid) + await websockets.close() async def __main2(self,clientid,websocket,path): "服务器端主逻辑" - async for message in websocket: - await self.onMessage(clientid, message) - await self.__onClose(clientid) + try: + async for message in websocket: + await self.onMessage(clientid, message) + except:pass + # await self.__onClose(clientid) await self.onClose(clientid) async def __main1(self,clientid,websocket,path): t = urllib.parse.parse_qs(urllib.parse.urlparse(path).query) @@ -306,6 +330,15 @@ class DFAFilter(): else: return False redis=kcwredis() +def timestampToDate(times,format="%Y-%m-%d %H:%M:%S"): + """时间戳转换时间 + + times 10位时间戳 + + format 日期格式 如%Y-%m-%d %H:%M:%S + """ + timeArray = time.localtime(int(times)) + return time.strftime(format.encode('unicode-escape').decode(),timeArray).encode().decode('unicode-escape') def send_mail(user,text="邮件内容",theme="邮件主题",recNick="收件人昵称"): """发送邮件 @@ -383,12 +416,23 @@ def Templates(path,**context): t=lookup.get_template(path) body=t.render(**context) return body -def getfunction(strs): +def kcwTemp(contents,**context): + "模板渲染引擎函数,传字符串进来" + lookup = TemplateLookup(directories=['']) + t=kcwTemplate(contents,lookup=lookup,module_directory=config.cache['path']+"/Template") + body=t.render(**context) + return body +def getfunction(strs,reload=False): """获取指定文件对象 strs :app.index.common.autoload 获取app/index/common/目录下的autoload对象 + + reload 是否重新加载已导入的模块(是否每次加载修改后的模块) """ - return importlib.import_module(strs) + obj=importlib.import_module(strs) + if reload: + importlib.reload(obj) + return obj def mysql(table=None,configss=None): """mysql数据库操作实例 @@ -514,7 +558,9 @@ def json_decode(strs): """json字符串转python类型""" try: return json.loads(strs) - except Exception: + except Exception as e: + if 'JSON object must be str, bytes or bytearray, not list' in str(e): + return strs return [] def json_encode(strs): """python列表或字典转成字符串""" @@ -558,7 +604,73 @@ def dateoperator(date,years=0,formats='%Y%m%d%H%M%S',months=0, days=0, hours=0, def get_folder(): '获取当前框架目录' return os.path.split(os.path.realpath(__file__))[0][:-7] #当前框架目录 -# aa=[] +def get_kcweb_cli_pid(route): + """通过路由地址获取pid""" + if not os.path.isfile(get_folder()+"/pid/"+md5(route)+"_cli_pid"): + return False + pid=False + with open(get_folder()+"/pid/"+md5(route)+"_cli_pid") as file: + pid = file.read() + return pid +def get_kcweb_cli_info(route,types='info'): + """通过路由地址获取进程信息 + + route 路由地址 + + types info表示获取进程信息 否则判断进程号是否存在 + """ + pid=get_kcweb_cli_pid(route) + if pid: + pid=int(pid) + try: + if types=='info': + p = psutil.Process(pid) + data={ + 'pid':pid, + 'name':p.name(), + 'cli':p.cmdline(), + 'cpu':p.cpu_percent(1), + 'memory':p.memory_info().rss + } + return data + else: + if psutil.pid_exists(pid): + return pid + else: + try: + os.remove(get_folder()+"/pid/"+md5(route)+"_cli_pid") + except:pass + return False + except: + return False + else: + return False +def kill_pid(pid): + """通过pid结束进程""" + if pid: + try: + os.kill(int(pid), signal.SIGTERM) + except:pass + # if get_sysinfo()['uname'][0]=='Linux': + # os.popen("kill -9 "+str(pid)) + # elif get_sysinfo()['uname'][0]=='Windows': + # os.popen("taskkill /PID "+str(pid)+" /F /T") + # else: + # raise Exception('不支持该系统') +def kill_route_cli(route): + """通过路由结束进程""" + pid=get_kcweb_cli_pid(route) + if pid: + kill_pid(pid) + try: + os.remove(get_folder()+"/pid/"+md5(route)+"_cli_pid") + except:pass +def save_route_cli_pid(route): + """通过路由保存pid""" + pid = os.getpid() + f=open(get_folder()+"/pid/"+md5(route)+"_cli_pid",'w') + f.write(str(pid)) + f.close() def get_file(folder='./',is_folder=True,suffix="*",lists=[],append=False): """获取文件夹下所有文件夹和文件 @@ -613,8 +725,83 @@ def list_to_tree(data, pk = 'id', pid = 'pid', child = 'lowerlist', root=0,child v[child]=kkkk arr.append(v) return arr +def randoms(lens=6,types=1): + """生成随机字符串 + + lens 长度 - + types 1数字 2字母 3字母加数字 + """ + strs="0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM,!@#$%^&*()_+=-;',./:<>?" + if types==1: + strs="0123456789" + elif types==2: + strs="qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM" + elif types==3: + strs="0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM" + k='' + i=0 + while i < lens: + k+=random.choice(strs) + i+=1 + return k +def file_set_content(k,data,encoding="utf-8"): + f=open(k,'w',encoding=encoding) + f.write(data) + f.close() + return True +def file_get_content(filename,encoding=False): + """获取文件内容 + + filename 完整文件名 + + encoding 是否返回文件编码 默认否 + """ + fileData='' + cur_encoding="utf-8" + if os.path.isfile(filename): + with open(filename, 'rb') as f: + cur_encoding = chardet.detect(f.read())['encoding'] + #用获取的编码读取该文件而不是python3默认的utf-8读取。 + with open(filename,encoding=cur_encoding) as file: + fileData = file.read() + if encoding: + return fileData,cur_encoding + else: + return fileData +class kcwebsign: + def getsign(params): + "获取签名" + if is_index(params,'sign'): + del params['sign'] + content=kcwebsign.getSignContent(params) + return md5(content) + def exsignpra(params): + "生成签名参数" + params['time']=times() + params['rands']=randoms() + params['sign']=kcwebsign.getsign(params) + return params + def getSignContent(params): + "字典排序" + param={} + for i in sorted (params) : + param[i]=params[i] + i=0 + strs="" + for k in param: + if k: + if isinstance(k,dict): + k=json_encode(k) + k=k.replace('"', '') + k=k.replace("'", '') + if param[k]: + if i==0: + strs+=str(k)+"="+str(param[k]) + else: + strs+="&"+str(k)+"="+str(param[k]) + i+=1 + return strs class kcwebzip: def packzip(src,dst): "压缩" @@ -814,9 +1001,9 @@ class response: header['Content-Type']="image/png" return body,status,header def video(body): - """输出音频 + """输出视频 - body 音频二进制内容或音频路径 + body 视频二进制内容或视频路径 """ status='200 ok' header={"Cache-Control":"public, max-age=2592000"} @@ -827,10 +1014,10 @@ class response: except: HTTP_IF_NONE_MATCH=None if(HTTP_IF_NONE_MATCH and get_cache(ETag)): + header=get_cache(ETag) status="304 Not Modified" body='' else: - set_cache(ETag,1,2592000) filename=body f=open(filename,"rb") body=f.read() @@ -840,6 +1027,8 @@ class response: header['Content-Type']=kind.mime except: header['Content-Type']="video/mp4" + header['content-length']=str(len(body)) + set_cache(ETag,header,2592000) dateArray = core_datetime.datetime.utcfromtimestamp(times()-86400) otherStyleTime = dateArray.strftime('%a, %d %b %Y %H:%M:%S GMT') header['Last-Modified']=otherStyleTime @@ -847,24 +1036,42 @@ class response: else: header['Content-Type']="video/mp4" return body,status,header - # def video(body): - # """输出音频 + def audio(body): + """输出音频 - # body 音频二进制内容或音频路径 - # """ - # if isinstance(body,str): - # filename=body - # f=open(filename,"rb") - # body=f.read() - # f.close() - # kind = filetype.guess(filename) - # try: - # ContentType=kind.mime - # except: - # ContentType="video/mp4" - # else: - # ContentType="video/mp4" - # return body,'200 ok',{"Content-Type":ContentType,"Cache-Control":"public, max-age=600"} + body 音频二进制内容或音频路径 + """ + status='200 ok' + header={"Cache-Control":"public, max-age=2592000"} + if isinstance(body,str): + ETag=md5(body) + try: + HTTP_IF_NONE_MATCH=globals.HEADER.GET['HTTP_IF_NONE_MATCH'] + except: + HTTP_IF_NONE_MATCH=None + if(HTTP_IF_NONE_MATCH and get_cache(ETag)): + header=get_cache(ETag) + status="304 Not Modified" + body='' + else: + filename=body + f=open(filename,"rb") + body=f.read() + f.close() + kind = filetype.guess(filename) + try: + header['Content-Type']=kind.mime + except: + header['Content-Type']="audio/mpeg" + header['content-length']=str(len(body)) + set_cache(ETag,header,2592000) + dateArray = core_datetime.datetime.utcfromtimestamp(times()-86400) + otherStyleTime = dateArray.strftime('%a, %d %b %Y %H:%M:%S GMT') + header['Last-Modified']=otherStyleTime + header['ETag']=ETag + else: + header['Content-Type']="audio/mpeg" + return body,status,header def download(pathname): """下载文件 @@ -895,26 +1102,34 @@ class response: header['Location']=url return html,status,header class create: + project='' appname=None modular=None path=get_folder() #当前框架目录 - def __init__(self,appname="app",modular="api"): + def __init__(self,appname="app",modular="api",project=''): self.appname=str(appname) self.modular=str(modular) + if project: + if os.path.exists(project): + print('项目已存在,请进入'+str(project)+'目录命令执行命令') + exit() + if not os.path.exists(self.appname): + self.project=str(project)+'/' + os.makedirs(self.project, exist_ok=True) def uninstallplug(self,plug): """卸载插件 plug 插件名 """ - f=open(self.appname+"/"+self.modular+"/controller/__init__.py","r",encoding='utf-8') + f=open(self.project+self.appname+"/"+self.modular+"/controller/__init__.py","r",encoding='utf-8') text=f.read() f.close() text=re.sub("\nfrom . import "+plug,"",text) text=re.sub("from . import "+plug,"",text) - f=open(self.appname+"/"+self.modular+"/controller/__init__.py","w",encoding='utf-8') + f=open(self.project+self.appname+"/"+self.modular+"/controller/__init__.py","w",encoding='utf-8') f.write(text) f.close() - shutil.rmtree(self.appname+"/"+self.modular+"/controller/"+plug) + shutil.rmtree(self.project+self.appname+"/"+self.modular+"/controller/"+plug) return True,"成功" def packplug(self,plug): """打包插件 @@ -922,18 +1137,19 @@ class create: plug 插件名 """ """打包模块""" - if os.path.exists(self.appname+"/"+self.modular+"/controller/"+plug): - kcwebzip.packzip(self.appname+"/"+self.modular+"/controller/"+plug,self.appname+"/"+self.modular+"/controller/"+plug+".zip") + if os.path.exists(self.project+self.appname+"/"+self.modular+"/controller/"+plug): + kcwebzip.packzip(self.project+self.appname+"/"+self.modular+"/controller/"+plug,self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip") return True,"成功" else: return False,"失败" - def uploadplug(self,plug,username='',password='',cli=False): + def uploadplug(self,plug,username='',password='',cli=False,relyonlist=[]): "上传一个插件" - if not os.path.isfile(self.appname+"/"+self.modular+"/controller/"+plug+".zip"): + if not os.path.isfile(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip"): self.packplug(plug=plug) i=0 http=Http() http.set_timeout=300 + relyonlist=json_encode(relyonlist) while True: timestamp=times() sign=md5(str(username)+str(timestamp)+md5(md5(password))) @@ -943,13 +1159,13 @@ class create: http.openurl(config.domain['kcwebapi']+"/user/userinfo/?username="+username+"×tamp="+str(timestamp)+"&sign="+sign) arr=json_decode(http.get_text) if not arr: - os.remove(self.appname+"/"+self.modular+"/controller/"+plug+".zip") + os.remove(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip") if config.app['app_debug']: print(http.get_text) return False,"用户身份验证失败,服务器暂时无法处理" if (arr['code']==-1 or arr['code']==2) and cli: if i >= 3: - os.remove(self.appname+"/"+self.modular+"/controller/"+plug+".zip") + os.remove(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip") return False,"用户名或密码错误" elif i: print("用户名或密码错误,请重新输入") @@ -962,36 +1178,36 @@ class create: elif arr['code']==0: break else: - os.remove(self.appname+"/"+self.modular+"/controller/"+plug+".zip") + os.remove(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip") return False,arr['msg'] http.openurl(config.domain['kcwebapi']+"/user/uploadplug/?username="+username+"×tamp="+str(timestamp)+"&sign="+sign,'POST', - data={'name':str(plug),'describes':'','modular':self.modular}, - files={'file':open(self.appname+"/"+self.modular+"/controller/"+plug+".zip", 'rb')}) + data={'name':str(plug),'describes':'','modular':self.modular,'relyonlist':relyonlist}, + files={'file':open(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip", 'rb')}) arr=json_decode(http.get_text) if not arr: - os.remove(self.appname+"/"+self.modular+"/controller/"+plug+".zip") + os.remove(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip") if config.app['app_debug']: print(http.get_text) return False,"上传失败,服务器暂时无法处理上传" elif arr['code']==-1 or arr['code']==2: - os.remove(self.appname+"/"+self.modular+"/controller/"+plug+".zip") + os.remove(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip") return False,"用户名或密码错误" elif arr['code']==0: - os.remove(self.appname+"/"+self.modular+"/controller/"+plug+".zip") + os.remove(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip") return True,arr['msg'] elif arr['code']==0: - os.remove(self.appname+"/"+self.modular+"/controller/"+plug+".zip") + os.remove(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip") return False,arr['msg'] else: - os.remove(self.appname+"/"+self.modular+"/controller/"+plug+".zip") + os.remove(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip") return False,arr['msg'] - def installplug(self,plug,edition='',token='',cli=False,mandatory=False): + def installplug(self,plug,edition='',token='',cli=False,mandatory=False,username=''): """创建一个插件,如果您的模块目录下没有插件包,则创建默认插件文件 plug 插件名 """ plug=str(plug) - if os.path.exists(self.appname+"/"+self.modular+"/controller/"+plug) and not mandatory: + if os.path.exists(self.project+self.appname+"/"+self.modular+"/controller/"+plug) and not mandatory: return False,"该插件已存在" else: http=Http() @@ -1000,7 +1216,7 @@ class create: tplug=plug modular=self.modular while True: - http.openurl(config.domain['kcwebapi']+"/pub/plug","GET",params={"modular":modular,"name":str(tplug),"edition":str(edition),"token":token}) + http.openurl(config.domain['kcwebapi']+"/pub/plug","GET",params={"modular":modular,"name":str(tplug),"edition":str(edition),"token":token,'username':username}) arr=json_decode(http.get_text) if arr: if arr['code']==-1 and cli: @@ -1013,7 +1229,9 @@ class create: i+=1 elif arr['code']==-1: return False,plug+"插件授权码错误" - elif not arr['data']: + elif arr['code']==-5: + return False,plug+","+arr['data'] + elif arr['code']==0 and not arr['data']: modular="api" tplug="index" #默认插件 elif arr['code']==0 and arr['data']: @@ -1021,12 +1239,12 @@ class create: j+=1 arr=arr['data'] r=requests.get(arr['dowurl'],verify=False) - f = open(self.appname+"/"+self.modular+"/controller/"+plug+".zip", "wb") + f = open(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip", "wb") for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) f.close() - if zipfile.is_zipfile(self.appname+"/"+self.modular+"/controller/"+plug+".zip") and os.path.isfile(self.appname+"/"+self.modular+"/controller/"+plug+".zip"): + if zipfile.is_zipfile(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip") and os.path.isfile(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip"): break if j >= 10: return False,str(plug)+"插件下载失败" @@ -1035,13 +1253,13 @@ class create: return False,str(plug)+"插件搜索失败" else: return False,self.modular+"模块下找不到"+str(plug)+"插件" - if os.path.isfile(self.appname+"/"+self.modular+"/controller/"+plug+".zip"):#安装打包好的插件 - kcwebzip.unzip_file(self.appname+"/"+self.modular+"/controller/"+plug+".zip",self.appname+"/"+self.modular+"/controller/"+plug+"/") - os.remove(self.appname+"/"+self.modular+"/controller/"+plug+".zip") - if os.path.isfile(self.appname+"/"+self.modular+"/controller/"+plug+"/install.txt"): #安装依赖包 + if os.path.isfile(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip"):#安装打包好的插件 + kcwebzip.unzip_file(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip",self.project+self.appname+"/"+self.modular+"/controller/"+plug+"/") + os.remove(self.project+self.appname+"/"+self.modular+"/controller/"+plug+".zip") + if os.path.isfile(self.project+self.appname+"/"+self.modular+"/controller/"+plug+"/install.txt"): #安装依赖包 install_requires=[] try: - f=open(self.appname+"/"+self.modular+"/controller/"+plug+"/install.txt") + f=open(self.project+self.appname+"/"+self.modular+"/controller/"+plug+"/install.txt") while True: line = f.readline() if not line: @@ -1050,51 +1268,51 @@ class create: install_requires.append(line) f.close() except: - shutil.rmtree(self.appname+"."+self.modular+"/controller/"+plug) - return False,"error" + shutil.rmtree(self.project+self.appname+"."+self.modular+"/controller/"+plug) + return False,"依赖包错误" if len(install_requires): try: install_requires.insert(0,"install") if 0 != pip.main(install_requires): - shutil.rmtree(self.appname+"/"+self.modular+"/controller/"+plug) - return False,"error" + shutil.rmtree(self.project+self.appname+"/"+self.modular+"/controller/"+plug) + return False,"依赖包安装错误" except AttributeError as e: - shutil.rmtree(self.appname+"/"+self.modular+"/controller/"+plug) + shutil.rmtree(self.project+self.appname+"/"+self.modular+"/controller/"+plug) if config.app['app_debug']: - print("建议更新您的pip版本。参考命令:Python -m pip install --user --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/") + print("建议更新您的pip版本。参考命令:python3 -m pip install --upgrade pip==21.2.4 -i https://mirrors.aliyun.com/pypi/simple/") return False,str(e) - if os.path.isfile(self.appname+"."+self.modular+"/controller/"+plug+"/install.py"): + if os.path.isfile(self.project+self.appname+"."+self.modular+"/controller/"+plug+"/install.py"): try: - m=importlib.import_module(self.appname+"."+self.modular+"/controller/"+plug+".install") + m=importlib.import_module(self.project+self.appname+"."+self.modular+"/controller/"+plug+".install") except: - shutil.rmtree(self.appname+"."+self.modular+"/controller/"+plug) + shutil.rmtree(self.project+self.appname+"."+self.modular+"/controller/"+plug) print(traceback.format_exc()) return False,"插件依赖包文件不存在或依赖包文件格式错误" else: try: a=m.install() except: - shutil.rmtree(self.appname+"."+self.modular+"/controller/"+plug) + shutil.rmtree(self.project+self.appname+"."+self.modular+"/controller/"+plug) return False,"插件依赖包install函数被破坏" # if not a[0]: - # shutil.rmtree(self.appname+"."+self.modular+"/controller/"+plug) + # shutil.rmtree(self.project+self.appname+"."+self.modular+"/controller/"+plug) # return False,str(a[1]) - f=open(self.appname+"/"+self.modular+"/controller/__init__.py","r",encoding='utf-8') + f=open(self.project+self.appname+"/"+self.modular+"/controller/__init__.py","r",encoding='utf-8') text=f.read() f.close() text=re.sub("\nfrom . import "+plug,"",text) text=re.sub("from . import "+plug,"",text) - f=open(self.appname+"/"+self.modular+"/controller/__init__.py","w",encoding='utf-8') + f=open(self.project+self.appname+"/"+self.modular+"/controller/__init__.py","w",encoding='utf-8') text+="\nfrom . import "+plug f.write(text) f.close() - f=open(self.appname+"/"+self.modular+"/controller/"+plug+"/common/autoload.py","r",encoding='utf-8') + f=open(self.project+self.appname+"/"+self.modular+"/controller/"+plug+"/common/autoload.py","r",encoding='utf-8') text=f.read() f.close() text=re.sub("app.api",self.appname+"."+self.modular,text) - f=open(self.appname+"/"+self.modular+"/controller/"+plug+"/common/autoload.py","w",encoding='utf-8') + f=open(self.project+self.appname+"/"+self.modular+"/controller/"+plug+"/common/autoload.py","w",encoding='utf-8') f.write(text) f.close() @@ -1104,30 +1322,31 @@ class create: return False,str(plug)+"插件获取失败" def uninstallmodular(self): "卸载模块" - f=open(self.appname+"/__init__.py","r") + f=open(self.project+self.appname+"/__init__.py","r") text=f.read() f.close() text=re.sub("\nfrom . import "+self.modular,"",text) text=re.sub("from . import "+self.modular,"",text) - f=open(self.appname+"/__init__.py","w") + f=open(self.project+self.appname+"/__init__.py","w") f.write(text) f.close() - shutil.rmtree(self.appname+"/"+self.modular) + shutil.rmtree(self.project+self.appname+"/"+self.modular) return True,"成功" def packmodular(self): """打包模块""" - if os.path.exists(self.appname+"/"+self.modular): - kcwebzip.packzip(self.appname+"/"+self.modular,self.appname+"/"+self.modular+".zip") + if os.path.exists(self.project+self.appname+"/"+self.modular): + kcwebzip.packzip(self.project+self.appname+"/"+self.modular,self.project+self.appname+"/"+self.modular+".zip") return True,"成功" else: return False,"失败" - def uploadmodular(self,username='',password='',cli=False): + def uploadmodular(self,username='',password='',cli=False,relyonlist=[]): "上传模块" - if not os.path.isfile(self.appname+"/"+self.modular+".zip"): + if not os.path.isfile(self.project+self.appname+"/"+self.modular+".zip"): self.packmodular() i=0 http=Http() http.set_timeout=300 + relyonlist=json_encode(relyonlist) while True: timestamp=times() sign=md5(str(username)+str(timestamp)+md5(md5(password))) @@ -1135,17 +1354,17 @@ class create: # http.set_header['timestamp']=str(timestamp) # http.set_header['sign']=sign http.openurl(config.domain['kcwebapi']+"/user/uploadmodular/?username="+username+"×tamp="+str(timestamp)+"&sign="+sign,'POST', - data={'name':str(self.modular),'describes':''}, - files={'file':open(self.appname+"/"+self.modular+".zip", 'rb')}) + data={'name':str(self.modular),'describes':'','relyonlist':relyonlist}, + files={'file':open(self.project+self.appname+"/"+self.modular+".zip", 'rb')}) arr=json_decode(http.get_text) if not arr: - os.remove(self.appname+"/"+self.modular+".zip") + os.remove(self.project+self.appname+"/"+self.modular+".zip") if config.app['app_debug']: print(http.get_text) return False,"用户身份验证失败,服务器暂时无法处理" if (arr['code']==-1 or arr['code']==2) and cli: if i >= 3: - os.remove(self.appname+"/"+self.modular+".zip") + os.remove(self.project+self.appname+"/"+self.modular+".zip") return False,"用户名或密码错误" elif i: print("用户名或密码错误,请重新输入") @@ -1158,94 +1377,110 @@ class create: elif arr['code']==0: break elif arr['code']==-1: - os.remove(self.appname+"/"+self.modular+".zip") + os.remove(self.project+self.appname+"/"+self.modular+".zip") return False,"用户名或密码错误" else: - os.remove(self.appname+"/"+self.modular+".zip") + os.remove(self.project+self.appname+"/"+self.modular+".zip") return False,arr['msg'] http.openurl(config.domain['kcwebapi']+"/user/uploadmodular/?username="+username+"×tamp="+str(timestamp)+"&sign="+sign,'POST', - data={'name':str(self.modular),'describes':''}, - files={'file':open(self.appname+"/"+self.modular+".zip", 'rb')}) + data={'name':str(self.modular),'describes':'','relyonlist':relyonlist}, + files={'file':open(self.project+self.appname+"/"+self.modular+".zip", 'rb')}) arr=json_decode(http.get_text) if not arr: - os.remove(self.appname+"/"+self.modular+".zip") + os.remove(self.project+self.appname+"/"+self.modular+".zip") if config.app['app_debug']: print(http.get_text) return False,"上传失败,服务器暂时无法处理上传" elif arr['code']==-1 or arr['code']==2: - os.remove(self.appname+"/"+self.modular+".zip") + os.remove(self.project+self.appname+"/"+self.modular+".zip") return False,"用户名或密码错误" elif arr['code']==0: - os.remove(self.appname+"/"+self.modular+".zip") + os.remove(self.project+self.appname+"/"+self.modular+".zip") return True,arr['msg'] else: - os.remove(self.appname+"/"+self.modular+".zip") + os.remove(self.project+self.appname+"/"+self.modular+".zip") return False,arr['msg'] - def installmodular(self,token='',cli=False): + def installmodular(self,token='',cli=False,package='kcweb'): "创建模块,如果应用不存,则创建默认应用,如果在您的应用目录下没有模块包,则创建默认模块文件" - if not os.path.exists(self.appname): - # os.makedirs(self.appname) - r=requests.get(config.domain['kcwebfile']+"/kcweb/app.zip") - f = open("./app.zip", "wb") - for chunk in r.iter_content(chunk_size=512): - if chunk: - f.write(chunk) - f.close() - kcwebzip.unzip_file("./app.zip","./"+self.appname) - os.remove("./app.zip") - if not os.path.isfile("./server.py"): - if "Windows" in platform.platform(): - pythonname="python" - else: - pythonname="python3" - servertext=('# -*- coding: utf-8 -*-\n #gunicorn -b 0.0.0.0:39010 '+self.appname+':app\n'+ - 'from kcweb import web\n'+ - 'import '+self.appname+' as application\n'+ - 'app=web(__name__,application)\n'+ + if not os.path.exists(self.project+self.appname): + if package=='kcwebplus': + r=requests.get(config.domain['kcwebfile']+"/kcweb/kcwebplus.zip") + f = open("./"+self.project+"kcwebplus.zip", "wb") + for chunk in r.iter_content(chunk_size=512): + if chunk: + f.write(chunk) + f.close() + kcwebzip.unzip_file("./"+self.project+"kcwebplus.zip","./"+self.project+self.appname) + os.remove("./"+self.project+"kcwebplus.zip") + else: + r=requests.get(config.domain['kcwebfile']+"/kcweb/app.zip") + f = open("./"+self.project+"app.zip", "wb") + for chunk in r.iter_content(chunk_size=512): + if chunk: + f.write(chunk) + f.close() + kcwebzip.unzip_file("./"+self.project+"app.zip","./"+self.project+self.appname) + os.remove("./"+self.project+"app.zip") + if not os.path.isfile("./"+self.project+"server.py"): + # if "Windows" in platform.platform(): + # pythonname="python" + # else: + # pythonname="python3.8" + servertext=('#项目运行文件,请务修改\n'+ + 'import kcweb,sys,'+self.appname+'\n'+ + 'app=kcweb.web(__name__,'+self.appname+')\n'+ 'if __name__ == "__main__":\n'+ - ' #host监听ip port端口 name python解释器名字 (windows一般是python linux一般是python3)\n'+ - ' app.run(host="0.0.0.0",port="39001",name="'+pythonname+'")') - f=open("./server.py","w+",encoding='utf-8') + ' try:\n'+ + ' route=sys.argv[1]\n'+ + ' if "eventlog"==route:\n'+ + ' raise Exception("")\n'+ + ' except:\n'+ + ' #host监听ip port端口 name python解释器名字 (windows一般是python linux一般是python3) \n'+ + ' app.run(host="0.0.0.0",port="39001",name="python3.8")\n'+ + ' else:\n'+ + ' app.cli(route)\n' + ) + f=open("./"+self.project+"server.py","w+",encoding='utf-8') f.write(servertext) f.close() - f=open(self.appname+"/common/autoload.py","w",encoding='utf-8') - f.write("from kcweb.common import *\n"+ - "from "+self.appname+" import config\n"+ - "G=globals.G") - f.close() - - content='' - f=open(self.appname+"/"+self.modular+"/common/autoload.py","r",encoding='utf-8') - while True: - line = f.readline() - if not line: - break - elif 'from' not in line and 'import' not in line: - content+=line - f.close() - f=open(self.appname+"/"+self.modular+"/common/autoload.py","w",encoding='utf-8') - f.write("from "+self.appname+".common import *\n"+content) - f.close() - - content='' - f=open(self.appname+"/"+self.modular+"/controller/index/common/autoload.py","r",encoding='utf-8') - while True: - line = f.readline() - if not line: - break - elif 'from' not in line and 'import' not in line: - content+=line - f.close() - f=open(self.appname+"/"+self.modular+"/controller/index/common/autoload.py","w",encoding='utf-8') - f.write("from "+self.appname+"."+self.modular+".common import *\n"+content) - f.close() + # f=open(self.project+self.appname+"/common/autoload.py","w",encoding='utf-8') + # f.write("from kcweb.common import *\n"+ + # "from "+self.appname+" import config\n"+ + # "G=globals.G") + # f.close() + + # content='' + # f=open(self.project+self.appname+"/"+self.modular+"/common/autoload.py","r",encoding='utf-8') + # while True: + # line = f.readline() + # if not line: + # break + # elif 'from' not in line and 'import' not in line: + # content+=line + # f.close() + # f=open(self.project+self.appname+"/"+self.modular+"/common/autoload.py","w",encoding='utf-8') + # f.write("from "+self.appname+".common import *\n"+content) + # f.close() + + # content='' + # f=open(self.project+self.appname+"/"+self.modular+"/controller/index/common/autoload.py","r",encoding='utf-8') + # while True: + # line = f.readline() + # if not line: + # break + # elif 'from' not in line and 'import' not in line: + # content+=line + # f.close() + # f=open(self.project+self.appname+"/"+self.modular+"/controller/index/common/autoload.py","w",encoding='utf-8') + # f.write("from "+self.appname+"."+self.modular+".common import *\n"+content) + # f.close() return True,"应用创建成功" else: - if not os.path.isfile(self.appname+"/__init__.py") or not os.path.exists(self.appname+"/common"): + if not os.path.isfile(self.project+self.appname+"/__init__.py") or not os.path.exists(self.project+self.appname+"/common"): return False,self.appname+"不是kcweb应用" - if os.path.exists(self.appname+"/"+self.modular): - return False,self.appname+"/"+self.modular+"已存在" + if os.path.exists(self.project+self.appname+"/"+self.modular): + return False,self.project+self.appname+"/"+self.modular+"已存在" else: http=Http() i=0 @@ -1272,23 +1507,23 @@ class create: i=0 while i < 5: r=requests.get(arr['dowurl']) - f = open(self.appname+"/"+self.modular+".zip", "wb") + f = open(self.project+self.appname+"/"+self.modular+".zip", "wb") for chunk in r.iter_content(chunk_size=1024*100): if chunk: f.write(chunk) f.close() time.sleep(0.3) - if os.path.isfile(self.appname+"/"+self.modular+".zip"): + if os.path.isfile(self.project+self.appname+"/"+self.modular+".zip"): break i+=1 - if os.path.isfile(self.appname+"/"+self.modular+".zip"):#安装打包好的模块 - kcwebzip.unzip_file(self.appname+"/"+self.modular+".zip",self.appname+"/"+self.modular+"/") - os.remove(self.appname+"/"+self.modular+".zip") + if os.path.isfile(self.project+self.appname+"/"+self.modular+".zip"):#安装打包好的模块 + kcwebzip.unzip_file(self.project+self.appname+"/"+self.modular+".zip",self.project+self.appname+"/"+self.modular+"/") + os.remove(self.project+self.appname+"/"+self.modular+".zip") - if os.path.isfile(self.appname+"/"+self.modular+"/install.txt"): #安装依赖包 + if os.path.isfile(self.project+self.appname+"/"+self.modular+"/install.txt"): #安装依赖包 install_requires=[] try: - f=open(self.appname+"/"+self.modular+"/install.txt") + f=open(self.project+self.appname+"/"+self.modular+"/install.txt") while True: line = f.readline() if not line: @@ -1297,42 +1532,42 @@ class create: install_requires.append(line) f.close() except: - shutil.rmtree(self.appname+"/"+self.modular) - return False,"error" + shutil.rmtree(self.project+self.appname+"/"+self.modular) + return False,"模块依赖包错误" if len(install_requires): try: install_requires.insert(0,"install") if 0 != pip.main(install_requires): - shutil.rmtree(self.appname+"/"+self.modular) - return False,"error" + shutil.rmtree(self.project+self.appname+"/"+self.modular) + return False,"模块依赖包安装错误" except AttributeError as e: - shutil.rmtree(self.appname+"/"+self.modular) + shutil.rmtree(self.project+self.appname+"/"+self.modular) if config.app['app_debug']: print("建议更新您的pip版本。参考命令:Python -m pip install --user --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/") return False,str(e) - if os.path.isfile(self.appname+"/"+self.modular+"/install.py"):#如果存在依赖文件 + if os.path.isfile(self.project+self.appname+"/"+self.modular+"/install.py"):#如果存在依赖文件 try: - m=importlib.import_module(self.appname+'.'+self.modular+'.install') + m=importlib.import_module(self.project+self.appname+'.'+self.modular+'.install') except: - shutil.rmtree(self.appname+"/"+self.modular) + shutil.rmtree(self.project+self.appname+"/"+self.modular) print(traceback.format_exc()) return False,"模块依赖包文件不存在或依赖包文件格式错误" else: try: a=m.install() except: - shutil.rmtree(self.appname+"/"+self.modular) + shutil.rmtree(self.project+self.appname+"/"+self.modular) return False,"模块依赖包install方法被破坏" # if not a[0]: - # shutil.rmtree(self.appname+"/"+self.modular) + # shutil.rmtree(self.project+self.appname+"/"+self.modular) # return False,str(a[1]) content="\nfrom . import "+self.modular - f=open(self.appname+"/__init__.py","a",encoding='utf-8') + f=open(self.project+self.appname+"/__init__.py","a",encoding='utf-8') f.write(content) f.close() content='' - f=open(self.appname+"/"+self.modular+"/common/autoload.py","r",encoding='utf-8') + f=open(self.project+self.appname+"/"+self.modular+"/common/autoload.py","r",encoding='utf-8') while True: line = f.readline() if not line: @@ -1340,22 +1575,22 @@ class create: elif 'from' not in line and 'import' not in line: content+=line f.close() - f=open(self.appname+"/"+self.modular+"/common/autoload.py","w",encoding='utf-8') + f=open(self.project+self.appname+"/"+self.modular+"/common/autoload.py","w",encoding='utf-8') f.write("from "+self.appname+".common import *\n"+content) f.close() - - content='' - f=open(self.appname+"/"+self.modular+"/controller/index/common/autoload.py","r",encoding='utf-8') - while True: - line = f.readline() - if not line: - break - elif 'from' not in line and 'import' not in line: - content+=line - f.close() - f=open(self.appname+"/"+self.modular+"/controller/index/common/autoload.py","w",encoding='utf-8') - f.write("from "+self.appname+"."+self.modular+".common import *\n"+content) - f.close() + if os.path.exists(self.project+self.appname+"/"+self.modular+"/controller/index"): + content='' + f=open(self.project+self.appname+"/"+self.modular+"/controller/index/common/autoload.py","r",encoding='utf-8') + while True: + line = f.readline() + if not line: + break + elif 'from' not in line and 'import' not in line: + content+=line + f.close() + f=open(self.project+self.appname+"/"+self.modular+"/controller/index/common/autoload.py","w",encoding='utf-8') + f.write("from "+self.appname+"."+self.modular+".common import *\n"+content) + f.close() else: return False,self.modular+"模块下载失败" if not os.path.isfile("./server.py"): @@ -1371,7 +1606,7 @@ class create: 'if __name__ == "__main__":\n'+ ' #host监听ip port端口 name python解释器名字 (windows一般是python linux一般是python3)\n'+ ' app.run(host="0.0.0.0",port="39001",name="'+pythonname+'")') - f=open("./server.py","w+",encoding='utf-8') + f=open("./"+self.project+"server.py","w+",encoding='utf-8') f.write(servertext) f.close() return True,"安装成功" @@ -1383,7 +1618,7 @@ class create: # def __zxmodular(self,sourcep): # "处理模块文件" # path1=self.path+"/application/api"+sourcep - # path2=self.appname+"/"+self.modular+sourcep + # path2=self.project+self.appname+"/"+self.modular+sourcep # lists=os.listdir(path1) # for files in lists: # if os.path.isfile(path1+"/"+files): @@ -1402,4 +1637,54 @@ class create: # elif files != '__pycache__': # if not os.path.exists(path2+"/"+files): # os.makedirs(path2+"/"+files) - # self.__zxmodular(sourcep+"/"+files) \ No newline at end of file + # self.__zxmodular(sourcep+"/"+files) +if not os.path.exists(get_folder()+"/pid/"): + os.makedirs(get_folder()+"/pid/", exist_ok=True) +if 'Linux' in get_sysinfo()['platform']: + #添加自启命令 + if not os.path.isfile('/usr/bin/startkcweb.sh'): + open('/usr/bin/startkcweb.sh', 'w').close() + os.system("sed -i 's/bash startkcweb.sh//g' /etc/rc.d/rc.local") + os.system("echo 'bash startkcweb.sh' >> /etc/rc.d/rc.local") + os.system('chmod 777 /etc/rc.d/rc.local') + os.system('chmod 777 /usr/bin/startkcweb.sh') +def insert_system_up(cmd): + """添加开机启动命令 + + cmd 命令 + """ + if 'Linux' in get_sysinfo()['platform']: + f=open("/usr/bin/startkcweb.sh","a") + f.write("\n"+cmd+"\n") + f.close() + return True + else: + raise Exception('暂不支持linux以外的系统') +def del_system_up(cmd,vague=False): + """删除开机启动命令 + + cmd 命令 + + vague 是否模糊匹配 + """ + if 'Linux' in get_sysinfo()['platform']: + if vague: + f = open("/usr/bin/startkcweb.sh") + con='' + while True: + line = f.readline() + if not line: + break + if cmd in line: + line='' + con=con+line + f.close() + file_set_content("/usr/bin/startkcweb.sh",con) + else: + content=file_get_content("/usr/bin/startkcweb.sh") + content=content.replace("\n"+cmd+"\n","") + file_set_content("/usr/bin/startkcweb.sh",content) + return True + else: + raise Exception('暂不支持linux以外的系统') + \ No newline at end of file diff --git a/common/globals.py b/kcweb/common/globals.py similarity index 100% rename from common/globals.py rename to kcweb/common/globals.py diff --git a/common/request.py b/kcweb/common/request.py similarity index 100% rename from common/request.py rename to kcweb/common/request.py diff --git a/common/session.py b/kcweb/common/session.py similarity index 100% rename from common/session.py rename to kcweb/common/session.py diff --git a/config/__init__.py b/kcweb/config/__init__.py similarity index 86% rename from config/__init__.py rename to kcweb/config/__init__.py index ccab9c90c33f5f6f56cbe1e1427152ab75490c82..d6188e99c4b5ae797d856df8d3815bf3041bfeab 100644 --- a/config/__init__.py +++ b/kcweb/config/__init__.py @@ -8,13 +8,8 @@ app['before_request']='' #设置请求前执行的函数 app['after_request']='' #设置请求后执行的函数 app['staticpath']='static' app['http_server']='wsgiref' #使用的开发服务器 支持 wsgiref、kcweb、kcweb_server -try: - if sys.argv[2]=='--cli': - app['cli']=True - else: - app['cli']=False -except: - app['cli']=False +app['cli']=False +app['save_cli_pid']=False #是否开启cli运行时保存pid # redis配置 redis={} redis['host']='127.0.0.1' #服务器地址 @@ -58,7 +53,7 @@ database['password']=['root'] #密码 [密码1,密码2,密码3...] database['db']=['test'] #数据库名 [数据库名1,数据库名2,数据库名3...] database['charset']='utf8mb4' #数据库编码默认采用utf8mb4 database['pattern']=False # True数据库长连接模式 False数据库短连接模式 注:建议web应用有效,cli应用方式下,如果长时间运行建议使用mysql().close()关闭 -database['cli']=app['cli'] # 是否以cli方式运行 +database['cli']=False # 是否以cli方式运行 database['dbObjcount']=1 # 连接池数量(单个数据库地址链接数量),数据库链接实例数量 mysql长链接模式下有效 database['deploy']=0 # 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) mysql数据库有效 database['master_num']=1 #主服务器数量 不能超过host服务器数量 (等于服务器数量表示读写不分离:主主复制。 小于服务器表示读写分离:主从复制。) mysql数据库有效 @@ -102,12 +97,12 @@ email['recNick']='' #默认收件人昵称 kcweb={} kcweb['name']='kcweb' #项目的名称 -kcweb['version']='4.13.26' #项目版本 -kcweb['description']='' #项目的简单描述 -kcweb['long_description']='' #项目详细描述 +kcweb['version']='5.328' #项目版本 +kcweb['description']='python web框架' #项目的简单描述 +kcweb['long_description']='kcweb作为web开发而设计的高性能框架,采用全新的架构思想,注重易用性。遵循MIT开源许可协议发布,意味着个人和企业可以免费使用kcweb,甚至允许把你基于kcweb开发的应用开源或商业产品发布或销售' #项目详细描述 kcweb['license']='MIT' #开源协议 mit开源 kcweb['url']='' -kcweb['author']='禄可集团-坤坤' #名字 +kcweb['author']='百里-坤坤' #名字 kcweb['author_email']='fk1402936534@qq.com' #邮件地址 kcweb['maintainer']='坤坤' #维护人员的名字 kcweb['maintainer_email']='fk1402936534@qq.com' #维护人员的邮件地址 @@ -115,11 +110,10 @@ kcweb['username']='' kcweb['password']='' domain={} -domain['kcwebfile']="https://fanshufile.oss-cn-beijing.aliyuncs.com" -domain['kcwebstatic']="https://fanshustatic.oss-cn-beijing.aliyuncs.com" -domain['kcwebimg']="https://fanshuimg.oss-cn-beijing.aliyuncs.com" -# domain['kcwebapi']="//kcweb.kwebapp.cn" -domain['kcwebapi']="http://124.223.99.60:49001/index/index" +domain['kcwebfile']="https://file.kwebapp.cn" +domain['kcwebstatic']="https://static.kwebapp.cn" +domain['kcwebimg']="https://img.kwebapp.cn" +domain['kcwebapi']="https://kcwebapi.kwebapp.cn" #其他配置 other={} diff --git a/kcweb/config/__pycache__/__init__.cpython-36.pyc b/kcweb/config/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07496b34237f06daed0791625bc6b24f3e35306b Binary files /dev/null and b/kcweb/config/__pycache__/__init__.cpython-36.pyc differ diff --git a/kcweb/kcweb.py b/kcweb/kcweb.py new file mode 100644 index 0000000000000000000000000000000000000000..b77fa7cba61a53cd4f8b6e8f0a8661379b0b96fd --- /dev/null +++ b/kcweb/kcweb.py @@ -0,0 +1,280 @@ +from .common import * +import getopt,site +PATH=os.getcwd() +sys.path.append(PATH) +# import subprocess +def __get_cmd_par(): + python_version=platform.python_version() + if python_version[0:3]!='3.8': + print("\033[1;31;40m "+config.kcweb['name']+"-"+config.kcweb['version']+"依赖python3.8,与你现在的python"+python_version+"不兼容") + exit() + try: + opts, args = getopt.getopt(sys.argv[1:], "h", ["project=","app=","modular=","plug=","user=","pwd=","host=","port=","timeout=","processcount=", + "install","uninstall","pack","upload","cli"]) + # print("opts",opts) + # print("args",args) + server=False + if 'server' in args: + server=True + help=False + if 'help' in args: + help=True + + project='' #项目名称 + appname='app' #应用名 目前是固定值 app + modular='index' #模块名 + plug='' #插件名 + username='' + password='' + host='0.0.0.0' + port=30000 + timeout='600' + processcount='4' + + install=False + uninstall=False + pack=False + upload=False + cli=False + + if '--cli' in args: + cli=True + i=0 + for data in opts: + if '--project' == data[0]: + project=data[1] + # if '--app' == data[0]: + # appname=data[1] + elif '--modular' == data[0]: + modular=data[1] + elif '--plug' == data[0]: + plug=data[1] + elif '--user' == data[0]: + username=data[1] + elif '--pwd' == data[0]: + password=data[1] + elif '--host' == data[0]: + host=data[1] + elif '--port' == data[0]: + port=data[1] + elif '--timeout' == data[0]: + timeout=data[1] + elif '--processcount' == data[0]: + processcount=data[1] + + elif '--help' == data[0]: + help=True + elif '--install' == data[0]: + install=True + elif '--uninstall' == data[0]: + uninstall=True + elif '--pack' == data[0]: + pack=True + elif '--upload' == data[0]: + upload=True + elif '--cli' == data[0]: + cli=True + i+=1 + except Exception as e: + try: + gcs=sys.argv[1] + except: + gcs='' + if gcs=='-v': + print(config.kcweb['name']+"-"+config.kcweb['version']) + else: + print("\033[1;31;40m有关kcweb命令的详细信息,请键入 kcweb help",e) + return False + else: + return { + 'server':server, + 'project':project,'appname':appname,'modular':modular,'username':username,'password':password,'plug':plug,'host':host,'port':port,'timeout':timeout,'processcount':processcount, + 'help':help,'install':install,'uninstall':uninstall,'pack':pack,'upload':upload,'cli':cli, + 'index':i + } +def executable(): + cmd_par=__get_cmd_par() + if not cmd_par: + exit() + if cmd_par['help']: + try: + cs=sys.argv[2:][0] + except: + cs=None + print("\033[1;31;40m有关某个命令的详细信息,请键入 kcweb help 命令名") + print("\033[36m执行 kcweb help server 可查看server相关命令") + print("\033[36m执行 kcweb help modular 可查看赋值相关命令") + print("\033[36m执行 kcweb help install 可查看安装相关命令") + print("\033[36m执行 kcweb help pack 可查看打包相关命令") + print("\033[36m执行 kcweb help upload 可查看上传相关命令") + print("\033[36m执行 kcweb help uninstall 可查看卸载相关命令\n") + if 'server' == cs: + print("\033[32mkcweb --host 0.0.0.0 --port 39001 server 启动web服务") + print("\033[32mhost、port并不是必须的,如果要使用默认值,您可以使用下面简短的命令来启动服务") + print("\033[32mkcweb server\n") + if 'modular' == cs: + print("\033[32mkcweb --modular api --plug plug --install 进行安装") + print("\033[1;31;40m初始化一个web应用示例,通常情况下modular、plug、install同时使用") + print("\033[32mmodular、plug并不是必须的,如果要使用默认值,您可以使用下面简短的命令来安装") + print("\033[32mkcweb install\n") + if 'install' == cs: + print("\033[32mkcweb --install 安装一个默认的应用") + print("\033[32mkcweb --modular base --install 在app应用中安装一个base模块") + print("\033[32mkcweb --modular base --plug plug1 --install 在app应用base模块中安装一个plug1插件") + print("\033[32mkcweb --modular intapp --plug plug1 --user 181*** --install 在app应用intapp模块中安装一个指定用户的plug1插件") + print("\033[32m如果您需要新建一个项目 可以使用以下命令") + print("\033[32mkcweb --project projectname --app app --modular intapp --plug plug1 --user 181*** --install 在projectname项目下的app应用下intapp模块中安装一个指定用户的plug1插件\n") + if 'pack' == cs: + print("\033[32mkcweb --modular api --pack 打包一个模块") + print("\033[32mkcweb --modular api --plug plug1 --pack 可以打包一个插件\n") + if 'upload' == cs: + print("\033[32mkcweb --modular intapp --user 181*** --pwd pwd123 --upload 上传一个intapp模块") + print("\033[32mkcweb --modular intapp --plug plug1 --user 181*** --pwd pwd123 --upload 向intapp模块中上传一个plug1插件") + print("\033[1;31;40m注意:181*** 和 pwd123 是您的用户或密码") + if 'uninstall' == cs: + print("\033[32mkcweb --modular api --uninstall 卸载app/api模块") + print("\033[32mkcweb --modular api --plug plug1 --uninstall 卸载app/api/plug1插件\n") + else: + # print(cmd_par) + if cmd_par['cli']:#通过命令行执行控制器的方法 + from . import web + try: + import app as application + except Exception as e: + if "No module named 'app'" in str(e): + print("请在kcweb项目下运行") + else: + print(traceback.format_exc()) + exit() + else: + app=web(__name__,application) + try: + RAW_URI=sys.argv[1] + except:pass + else: + if RAW_URI=='--cli': + RAW_URI='' + app.cli(RAW_URI) + elif cmd_par['server']:#启动web服务 + types=sys.argv[len(sys.argv)-1] + try: + Queues.delwhere("code in (2,3)") + except:pass + if get_sysinfo()['uname'][0]=='Linux': + pythonpath=site.getsitepackages()[0].replace('\\','/') + t=pythonpath.split('/') + tt='/'+t[-3]+'/'+t[-2]+'/'+t[-1] + pythonpath=pythonpath.replace(tt,'') + if not os.path.exists('/usr/bin/kcweb') and os.path.isfile(pythonpath+'/bin/kcweb'): + os.system("ln -s "+pythonpath+"/bin/kcweb /usr/bin/kcweb") + # if types=='-stop' or types=='-start': + # pass + # else: + # print("启动参数错误,支持 -start和-stop") + # exit() + # try: + # f=open("pid",'r') + # pid=f.read() + # f.close() + # if pid: + # os.system("kill "+pid) + # except:pass + if __name__ == 'kcweb.kcweb': + kill_route_cli('pid/kcweb_server_pid') + if types=='-stop': + pass + else: + save_route_cli_pid('pid/kcweb_server_pid') + from gunicorn.app.wsgiapp import run + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$','',sys.argv[0]) + sys.argv=[sys.argv[0], '-w', str(cmd_par['processcount']), '-b', cmd_par['host']+':'+str(cmd_par['port']),'-t',cmd_par['timeout'], 'server:'+cmd_par['appname']] + sys.exit(run()) + exit() + else: + + from . import web + try: + import app as application + except Exception as e: + if "No module named 'app'" in str(e): + print("请在kcweb项目下运行") + else: + print(traceback.format_exc()) + exit() + else: + app=web(__name__,application) + if __name__ == "kcweb.kcweb": + tar=len(sys.argv) + kill_route_cli('pid/'+str(sys.argv[tar-1])+'kcweb_server_pid') + if types=='-stop': + pass + else: + save_route_cli_pid('pid/'+str(sys.argv[tar-1])+'kcweb_server_pid') + app.run(host=cmd_par['host'],port=int(cmd_par['port'])) + else: + if cmd_par['install']:#插入 应用、模块、插件 + if cmd_par['appname'] and cmd_par['modular']: + server=create(cmd_par['appname'],cmd_par['modular'],project=cmd_par['project']) + t=server.installmodular(cli=True) + if cmd_par['plug']: + res=server.installplug(cmd_par['plug'],cli=True,username=cmd_par['username']) + print(res) + if not res[0]: + exit() + else: + if '应用创建成功' in t[1]: + print("创建应用成功,接下来进入入项目目录 在终端中执行:kcweb server 运行项目") + else: + print(t) + else: + print("\033[1;31;40m安装时 必须指定应该app和modular,参考命令: kcweb --app app --modular api") + exit() + if cmd_par['pack']:#打包 模块、插件 + if cmd_par['appname'] and cmd_par['modular']: + server=create(cmd_par['appname'],cmd_par['modular'],project=cmd_par['project']) + if cmd_par['plug']: + res=server.packplug(plug=cmd_par['plug']) + else: + res=server.packmodular() + print(res) + if not res[0]: + exit() + else: + print("\033[1;31;40m打包时 必须指定应该app和modular,参考命令: kcweb --app app --modular api") + exit() + if cmd_par['upload']:#上传 模块、插件 + if cmd_par['appname'] and cmd_par['modular']: + server=create(cmd_par['appname'],cmd_par['modular'],project=cmd_par['project']) + if cmd_par['plug']: + res=server.packplug(plug=cmd_par['plug']) + if res[0]: + res=server.uploadplug(cmd_par['plug'],cmd_par['username'],cmd_par['password'],cli=True) + else: + print(res) + exit() + else: + res=server.packmodular() + if res[0]: + res=server.uploadmodular(cmd_par['username'],cmd_par['password'],cli=True) + else: + print(res) + exit() + print(res) + if not res[0]: + exit() + else: + print("\033[1;31;40m上传时 必须指定应该app和modular,参考命令: kcweb --app app --modular api") + exit() + if cmd_par['uninstall']:#卸载 模块、插件 + if cmd_par['appname'] and cmd_par['modular']: + server=create(cmd_par['appname'],cmd_par['modular'],project=cmd_par['project']) + if cmd_par['plug']: + res=server.uninstallplug(plug=cmd_par['plug']) + else: + res=server.uninstallmodular() + print(res) + if not res[0]: + exit() + else: + print("\033[1;31;40m卸载时 必须指定应该app和modular,参考命令: kcweb --app app --modular api") + exit() \ No newline at end of file diff --git a/tpl/err.html b/kcweb/tpl/err.html similarity index 100% rename from tpl/err.html rename to kcweb/tpl/err.html diff --git a/tpl/error.html b/kcweb/tpl/error.html similarity index 100% rename from tpl/error.html rename to kcweb/tpl/error.html diff --git a/kcweb/utill/__pycache__/http.cpython-36.pyc b/kcweb/utill/__pycache__/http.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9dd39e0ea419022810cec0faafd0f6d235aa5fb1 Binary files /dev/null and b/kcweb/utill/__pycache__/http.cpython-36.pyc differ diff --git a/kcweb/utill/__pycache__/queues.cpython-36.pyc b/kcweb/utill/__pycache__/queues.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8586926c4cb8aba51160942d1c4936daee69831f Binary files /dev/null and b/kcweb/utill/__pycache__/queues.cpython-36.pyc differ diff --git a/kcweb/utill/__pycache__/redis.cpython-36.pyc b/kcweb/utill/__pycache__/redis.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..686d0a666ea2da83b8e5a5338a97675cb4136ca3 Binary files /dev/null and b/kcweb/utill/__pycache__/redis.cpython-36.pyc differ diff --git a/utill/app.py b/kcweb/utill/app.py similarity index 100% rename from utill/app.py rename to kcweb/utill/app.py diff --git a/kcweb/utill/cache/__pycache__/cache.cpython-36.pyc b/kcweb/utill/cache/__pycache__/cache.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..af3601d0b641120085d3bbc090e85974dac0a19b Binary files /dev/null and b/kcweb/utill/cache/__pycache__/cache.cpython-36.pyc differ diff --git a/utill/cache/cache.py b/kcweb/utill/cache/cache.py similarity index 100% rename from utill/cache/cache.py rename to kcweb/utill/cache/cache.py diff --git a/utill/dateutil/__init__.py b/kcweb/utill/dateutil/__init__.py similarity index 100% rename from utill/dateutil/__init__.py rename to kcweb/utill/dateutil/__init__.py diff --git a/kcweb/utill/dateutil/__pycache__/__init__.cpython-36.pyc b/kcweb/utill/dateutil/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..509c0785a3b66a6123848e17b71e36a95acb404a Binary files /dev/null and b/kcweb/utill/dateutil/__pycache__/__init__.cpython-36.pyc differ diff --git a/kcweb/utill/dateutil/__pycache__/_common.cpython-36.pyc b/kcweb/utill/dateutil/__pycache__/_common.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3f2a89c744bcb0929914ff577528f14c9698fc6 Binary files /dev/null and b/kcweb/utill/dateutil/__pycache__/_common.cpython-36.pyc differ diff --git a/kcweb/utill/dateutil/__pycache__/_version.cpython-36.pyc b/kcweb/utill/dateutil/__pycache__/_version.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e507bf19823cf04e4b59bddc203aff57a4a039c0 Binary files /dev/null and b/kcweb/utill/dateutil/__pycache__/_version.cpython-36.pyc differ diff --git a/kcweb/utill/dateutil/__pycache__/relativedelta.cpython-36.pyc b/kcweb/utill/dateutil/__pycache__/relativedelta.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e476ac5a7c32fef2824849251c5b8f2129003c71 Binary files /dev/null and b/kcweb/utill/dateutil/__pycache__/relativedelta.cpython-36.pyc differ diff --git a/utill/dateutil/_common.py b/kcweb/utill/dateutil/_common.py similarity index 100% rename from utill/dateutil/_common.py rename to kcweb/utill/dateutil/_common.py diff --git a/utill/dateutil/_version.py b/kcweb/utill/dateutil/_version.py similarity index 100% rename from utill/dateutil/_version.py rename to kcweb/utill/dateutil/_version.py diff --git a/utill/dateutil/easter.py b/kcweb/utill/dateutil/easter.py similarity index 100% rename from utill/dateutil/easter.py rename to kcweb/utill/dateutil/easter.py diff --git a/utill/dateutil/parser/__init__.py b/kcweb/utill/dateutil/parser/__init__.py similarity index 100% rename from utill/dateutil/parser/__init__.py rename to kcweb/utill/dateutil/parser/__init__.py diff --git a/utill/dateutil/parser/_parser.py b/kcweb/utill/dateutil/parser/_parser.py similarity index 100% rename from utill/dateutil/parser/_parser.py rename to kcweb/utill/dateutil/parser/_parser.py diff --git a/utill/dateutil/parser/isoparser.py b/kcweb/utill/dateutil/parser/isoparser.py similarity index 100% rename from utill/dateutil/parser/isoparser.py rename to kcweb/utill/dateutil/parser/isoparser.py diff --git a/utill/dateutil/relativedelta.py b/kcweb/utill/dateutil/relativedelta.py similarity index 100% rename from utill/dateutil/relativedelta.py rename to kcweb/utill/dateutil/relativedelta.py diff --git a/utill/dateutil/rrule.py b/kcweb/utill/dateutil/rrule.py similarity index 100% rename from utill/dateutil/rrule.py rename to kcweb/utill/dateutil/rrule.py diff --git a/utill/dateutil/tz/__init__.py b/kcweb/utill/dateutil/tz/__init__.py similarity index 100% rename from utill/dateutil/tz/__init__.py rename to kcweb/utill/dateutil/tz/__init__.py diff --git a/utill/dateutil/tz/_common.py b/kcweb/utill/dateutil/tz/_common.py similarity index 100% rename from utill/dateutil/tz/_common.py rename to kcweb/utill/dateutil/tz/_common.py diff --git a/utill/dateutil/tz/_factories.py b/kcweb/utill/dateutil/tz/_factories.py similarity index 100% rename from utill/dateutil/tz/_factories.py rename to kcweb/utill/dateutil/tz/_factories.py diff --git a/utill/dateutil/tz/tz.py b/kcweb/utill/dateutil/tz/tz.py similarity index 100% rename from utill/dateutil/tz/tz.py rename to kcweb/utill/dateutil/tz/tz.py diff --git a/utill/dateutil/tz/win.py b/kcweb/utill/dateutil/tz/win.py similarity index 100% rename from utill/dateutil/tz/win.py rename to kcweb/utill/dateutil/tz/win.py diff --git a/utill/dateutil/tzwin.py b/kcweb/utill/dateutil/tzwin.py similarity index 100% rename from utill/dateutil/tzwin.py rename to kcweb/utill/dateutil/tzwin.py diff --git a/utill/dateutil/utils.py b/kcweb/utill/dateutil/utils.py similarity index 100% rename from utill/dateutil/utils.py rename to kcweb/utill/dateutil/utils.py diff --git a/utill/dateutil/zoneinfo/__init__.py b/kcweb/utill/dateutil/zoneinfo/__init__.py similarity index 100% rename from utill/dateutil/zoneinfo/__init__.py rename to kcweb/utill/dateutil/zoneinfo/__init__.py diff --git a/utill/dateutil/zoneinfo/rebuild.py b/kcweb/utill/dateutil/zoneinfo/rebuild.py similarity index 100% rename from utill/dateutil/zoneinfo/rebuild.py rename to kcweb/utill/dateutil/zoneinfo/rebuild.py diff --git a/kcweb/utill/db/__pycache__/model.cpython-36.pyc b/kcweb/utill/db/__pycache__/model.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..90b4af7780515fff87a11611cdd2be7ea881be96 Binary files /dev/null and b/kcweb/utill/db/__pycache__/model.cpython-36.pyc differ diff --git a/kcweb/utill/db/__pycache__/mongodb.cpython-36.pyc b/kcweb/utill/db/__pycache__/mongodb.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f5937ea50adb2ba56f80569ab167fadf88b14352 Binary files /dev/null and b/kcweb/utill/db/__pycache__/mongodb.cpython-36.pyc differ diff --git a/kcweb/utill/db/__pycache__/mysql.cpython-36.pyc b/kcweb/utill/db/__pycache__/mysql.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c02e527d62476b747dcd6f2c1d66f1b1e87c4971 Binary files /dev/null and b/kcweb/utill/db/__pycache__/mysql.cpython-36.pyc differ diff --git a/kcweb/utill/db/__pycache__/sqlite.cpython-36.pyc b/kcweb/utill/db/__pycache__/sqlite.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..73c876945ba43e0a9c791b8c844cb241849e2cdd Binary files /dev/null and b/kcweb/utill/db/__pycache__/sqlite.cpython-36.pyc differ diff --git a/utill/db/model.py b/kcweb/utill/db/model.py similarity index 100% rename from utill/db/model.py rename to kcweb/utill/db/model.py diff --git a/utill/db/mongodb.py b/kcweb/utill/db/mongodb.py similarity index 100% rename from utill/db/mongodb.py rename to kcweb/utill/db/mongodb.py diff --git a/utill/db/mysql.py b/kcweb/utill/db/mysql.py similarity index 100% rename from utill/db/mysql.py rename to kcweb/utill/db/mysql.py diff --git a/utill/db/pymysql/__init__.py b/kcweb/utill/db/pymysql/__init__.py similarity index 100% rename from utill/db/pymysql/__init__.py rename to kcweb/utill/db/pymysql/__init__.py diff --git a/kcweb/utill/db/pymysql/__pycache__/__init__.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c781e16d74ae1342a5a843a31bd69e9fad7f70d6 Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/__init__.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/__pycache__/_auth.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/_auth.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..57b3c43f07ff799d319352469e73bf2319ee3bbf Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/_auth.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/__pycache__/_compat.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/_compat.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9de03b094ad6ccf46f6fb9783fa7bef1cdd0d102 Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/_compat.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/__pycache__/charset.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/charset.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..676143078bad99bb3bd68c7bd46bc3daa0798013 Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/charset.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/__pycache__/connections.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/connections.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef312c359d2bc834617f02492d144c2105c30a08 Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/connections.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/__pycache__/converters.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/converters.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c6ba9b8868d22ce7710033bb0b0dad2438769f10 Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/converters.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/__pycache__/cursors.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/cursors.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4360937cae8b9737d28760a7161092324cb44a7e Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/cursors.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/__pycache__/err.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/err.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a9a0db3797740590a5ca462b1810b0d79e82e805 Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/err.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/__pycache__/optionfile.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/optionfile.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a7f0a629fa0fe2cae94b8b52b623fde491ee5c26 Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/optionfile.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/__pycache__/protocol.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/protocol.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c99007e3dd8b56d689d9b18e01ae4b62d030d373 Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/protocol.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/__pycache__/times.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/times.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d2fec599280f6a27abb1acfdc9c9390bf7f465f Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/times.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/__pycache__/util.cpython-36.pyc b/kcweb/utill/db/pymysql/__pycache__/util.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1764e844120467d961eb138dbb1aceacb3caf4ed Binary files /dev/null and b/kcweb/utill/db/pymysql/__pycache__/util.cpython-36.pyc differ diff --git a/utill/db/pymysql/_auth.py b/kcweb/utill/db/pymysql/_auth.py similarity index 100% rename from utill/db/pymysql/_auth.py rename to kcweb/utill/db/pymysql/_auth.py diff --git a/utill/db/pymysql/_compat.py b/kcweb/utill/db/pymysql/_compat.py similarity index 100% rename from utill/db/pymysql/_compat.py rename to kcweb/utill/db/pymysql/_compat.py diff --git a/utill/db/pymysql/_socketio.py b/kcweb/utill/db/pymysql/_socketio.py similarity index 100% rename from utill/db/pymysql/_socketio.py rename to kcweb/utill/db/pymysql/_socketio.py diff --git a/utill/db/pymysql/charset.py b/kcweb/utill/db/pymysql/charset.py similarity index 100% rename from utill/db/pymysql/charset.py rename to kcweb/utill/db/pymysql/charset.py diff --git a/utill/db/pymysql/connections.py b/kcweb/utill/db/pymysql/connections.py similarity index 100% rename from utill/db/pymysql/connections.py rename to kcweb/utill/db/pymysql/connections.py diff --git a/utill/db/pymysql/constants/CLIENT.py b/kcweb/utill/db/pymysql/constants/CLIENT.py similarity index 100% rename from utill/db/pymysql/constants/CLIENT.py rename to kcweb/utill/db/pymysql/constants/CLIENT.py diff --git a/utill/db/pymysql/constants/COMMAND.py b/kcweb/utill/db/pymysql/constants/COMMAND.py similarity index 100% rename from utill/db/pymysql/constants/COMMAND.py rename to kcweb/utill/db/pymysql/constants/COMMAND.py diff --git a/utill/db/pymysql/constants/CR.py b/kcweb/utill/db/pymysql/constants/CR.py similarity index 100% rename from utill/db/pymysql/constants/CR.py rename to kcweb/utill/db/pymysql/constants/CR.py diff --git a/utill/db/pymysql/constants/ER.py b/kcweb/utill/db/pymysql/constants/ER.py similarity index 100% rename from utill/db/pymysql/constants/ER.py rename to kcweb/utill/db/pymysql/constants/ER.py diff --git a/utill/db/pymysql/constants/FIELD_TYPE.py b/kcweb/utill/db/pymysql/constants/FIELD_TYPE.py similarity index 100% rename from utill/db/pymysql/constants/FIELD_TYPE.py rename to kcweb/utill/db/pymysql/constants/FIELD_TYPE.py diff --git a/utill/db/pymysql/constants/FLAG.py b/kcweb/utill/db/pymysql/constants/FLAG.py similarity index 100% rename from utill/db/pymysql/constants/FLAG.py rename to kcweb/utill/db/pymysql/constants/FLAG.py diff --git a/utill/db/pymysql/constants/SERVER_STATUS.py b/kcweb/utill/db/pymysql/constants/SERVER_STATUS.py similarity index 100% rename from utill/db/pymysql/constants/SERVER_STATUS.py rename to kcweb/utill/db/pymysql/constants/SERVER_STATUS.py diff --git a/utill/db/pymysql/constants/__init__.py b/kcweb/utill/db/pymysql/constants/__init__.py similarity index 100% rename from utill/db/pymysql/constants/__init__.py rename to kcweb/utill/db/pymysql/constants/__init__.py diff --git a/kcweb/utill/db/pymysql/constants/__pycache__/CLIENT.cpython-36.pyc b/kcweb/utill/db/pymysql/constants/__pycache__/CLIENT.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc727edc791134ec2e2840d7e0606838bc2688cd Binary files /dev/null and b/kcweb/utill/db/pymysql/constants/__pycache__/CLIENT.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/constants/__pycache__/COMMAND.cpython-36.pyc b/kcweb/utill/db/pymysql/constants/__pycache__/COMMAND.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2a6acec4242571b9ed2fcebc19a4c3de247abae Binary files /dev/null and b/kcweb/utill/db/pymysql/constants/__pycache__/COMMAND.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/constants/__pycache__/CR.cpython-36.pyc b/kcweb/utill/db/pymysql/constants/__pycache__/CR.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c1a759743a3cd2a6f8444eaf8dd07f3d03f6b2b Binary files /dev/null and b/kcweb/utill/db/pymysql/constants/__pycache__/CR.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/constants/__pycache__/ER.cpython-36.pyc b/kcweb/utill/db/pymysql/constants/__pycache__/ER.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..982e80578079f4257478e802d795965588c9de59 Binary files /dev/null and b/kcweb/utill/db/pymysql/constants/__pycache__/ER.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/constants/__pycache__/FIELD_TYPE.cpython-36.pyc b/kcweb/utill/db/pymysql/constants/__pycache__/FIELD_TYPE.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8dc47c2face04270335e1437eba89a3f4efc935a Binary files /dev/null and b/kcweb/utill/db/pymysql/constants/__pycache__/FIELD_TYPE.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/constants/__pycache__/FLAG.cpython-36.pyc b/kcweb/utill/db/pymysql/constants/__pycache__/FLAG.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2b0038b9e1a7338e8567ccef6d5e99213454c5f3 Binary files /dev/null and b/kcweb/utill/db/pymysql/constants/__pycache__/FLAG.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/constants/__pycache__/SERVER_STATUS.cpython-36.pyc b/kcweb/utill/db/pymysql/constants/__pycache__/SERVER_STATUS.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c2dd4406e72885dacc69398ba4f90085d4728ef Binary files /dev/null and b/kcweb/utill/db/pymysql/constants/__pycache__/SERVER_STATUS.cpython-36.pyc differ diff --git a/kcweb/utill/db/pymysql/constants/__pycache__/__init__.cpython-36.pyc b/kcweb/utill/db/pymysql/constants/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0412b212026fc4ce25d491dca6fd7b731115c0e3 Binary files /dev/null and b/kcweb/utill/db/pymysql/constants/__pycache__/__init__.cpython-36.pyc differ diff --git a/utill/db/pymysql/converters.py b/kcweb/utill/db/pymysql/converters.py similarity index 100% rename from utill/db/pymysql/converters.py rename to kcweb/utill/db/pymysql/converters.py diff --git a/utill/db/pymysql/cursors.py b/kcweb/utill/db/pymysql/cursors.py similarity index 100% rename from utill/db/pymysql/cursors.py rename to kcweb/utill/db/pymysql/cursors.py diff --git a/utill/db/pymysql/err.py b/kcweb/utill/db/pymysql/err.py similarity index 100% rename from utill/db/pymysql/err.py rename to kcweb/utill/db/pymysql/err.py diff --git a/utill/db/pymysql/optionfile.py b/kcweb/utill/db/pymysql/optionfile.py similarity index 100% rename from utill/db/pymysql/optionfile.py rename to kcweb/utill/db/pymysql/optionfile.py diff --git a/utill/db/pymysql/protocol.py b/kcweb/utill/db/pymysql/protocol.py similarity index 100% rename from utill/db/pymysql/protocol.py rename to kcweb/utill/db/pymysql/protocol.py diff --git a/utill/db/pymysql/times.py b/kcweb/utill/db/pymysql/times.py similarity index 100% rename from utill/db/pymysql/times.py rename to kcweb/utill/db/pymysql/times.py diff --git a/utill/db/pymysql/util.py b/kcweb/utill/db/pymysql/util.py similarity index 100% rename from utill/db/pymysql/util.py rename to kcweb/utill/db/pymysql/util.py diff --git a/utill/db/sqlite.py b/kcweb/utill/db/sqlite.py similarity index 100% rename from utill/db/sqlite.py rename to kcweb/utill/db/sqlite.py diff --git a/utill/db/sqlitedata/kcwdb b/kcweb/utill/db/sqlitedata/kcwdb similarity index 100% rename from utill/db/sqlitedata/kcwdb rename to kcweb/utill/db/sqlitedata/kcwdb diff --git a/utill/filetype/__init__.py b/kcweb/utill/filetype/__init__.py similarity index 100% rename from utill/filetype/__init__.py rename to kcweb/utill/filetype/__init__.py diff --git a/kcweb/utill/filetype/__pycache__/__init__.cpython-36.pyc b/kcweb/utill/filetype/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..154205f26626baa206ea2df39b28c4bddab3b558 Binary files /dev/null and b/kcweb/utill/filetype/__pycache__/__init__.cpython-36.pyc differ diff --git a/kcweb/utill/filetype/__pycache__/filetype.cpython-36.pyc b/kcweb/utill/filetype/__pycache__/filetype.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..237061ace833c009eb22c2becefe4e5265194c6e Binary files /dev/null and b/kcweb/utill/filetype/__pycache__/filetype.cpython-36.pyc differ diff --git a/kcweb/utill/filetype/__pycache__/helpers.cpython-36.pyc b/kcweb/utill/filetype/__pycache__/helpers.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7364051f69e84d4d73ca37d646ec1ca8151e865f Binary files /dev/null and b/kcweb/utill/filetype/__pycache__/helpers.cpython-36.pyc differ diff --git a/kcweb/utill/filetype/__pycache__/match.cpython-36.pyc b/kcweb/utill/filetype/__pycache__/match.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f14325fa64c7572afbc649705272dde3a5c76718 Binary files /dev/null and b/kcweb/utill/filetype/__pycache__/match.cpython-36.pyc differ diff --git a/kcweb/utill/filetype/__pycache__/utils.cpython-36.pyc b/kcweb/utill/filetype/__pycache__/utils.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e423806a12cc727f695120c189bc1927a82a219 Binary files /dev/null and b/kcweb/utill/filetype/__pycache__/utils.cpython-36.pyc differ diff --git a/utill/filetype/filetype.py b/kcweb/utill/filetype/filetype.py similarity index 100% rename from utill/filetype/filetype.py rename to kcweb/utill/filetype/filetype.py diff --git a/utill/filetype/helpers.py b/kcweb/utill/filetype/helpers.py similarity index 100% rename from utill/filetype/helpers.py rename to kcweb/utill/filetype/helpers.py diff --git a/utill/filetype/match.py b/kcweb/utill/filetype/match.py similarity index 100% rename from utill/filetype/match.py rename to kcweb/utill/filetype/match.py diff --git a/utill/filetype/types/__init__.py b/kcweb/utill/filetype/types/__init__.py similarity index 100% rename from utill/filetype/types/__init__.py rename to kcweb/utill/filetype/types/__init__.py diff --git a/kcweb/utill/filetype/types/__pycache__/__init__.cpython-36.pyc b/kcweb/utill/filetype/types/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..904083e8d25c8fae512eb7032aafc3d735c96e2d Binary files /dev/null and b/kcweb/utill/filetype/types/__pycache__/__init__.cpython-36.pyc differ diff --git a/kcweb/utill/filetype/types/__pycache__/archive.cpython-36.pyc b/kcweb/utill/filetype/types/__pycache__/archive.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e1cccd15ce0ce5ebac7ee26f7eb039762cd9eef Binary files /dev/null and b/kcweb/utill/filetype/types/__pycache__/archive.cpython-36.pyc differ diff --git a/kcweb/utill/filetype/types/__pycache__/audio.cpython-36.pyc b/kcweb/utill/filetype/types/__pycache__/audio.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..943f60d991fd228cc08244b50e09e556a2913397 Binary files /dev/null and b/kcweb/utill/filetype/types/__pycache__/audio.cpython-36.pyc differ diff --git a/kcweb/utill/filetype/types/__pycache__/base.cpython-36.pyc b/kcweb/utill/filetype/types/__pycache__/base.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0397ea0f1f9fab292521aa26aca7c138ae10a0c Binary files /dev/null and b/kcweb/utill/filetype/types/__pycache__/base.cpython-36.pyc differ diff --git a/kcweb/utill/filetype/types/__pycache__/font.cpython-36.pyc b/kcweb/utill/filetype/types/__pycache__/font.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d3cb8c67417dbe76d1b63f75a61ef663ea76286 Binary files /dev/null and b/kcweb/utill/filetype/types/__pycache__/font.cpython-36.pyc differ diff --git a/kcweb/utill/filetype/types/__pycache__/image.cpython-36.pyc b/kcweb/utill/filetype/types/__pycache__/image.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..488dcaeb941ce4b318520719744887005dc6a71f Binary files /dev/null and b/kcweb/utill/filetype/types/__pycache__/image.cpython-36.pyc differ diff --git a/kcweb/utill/filetype/types/__pycache__/isobmff.cpython-36.pyc b/kcweb/utill/filetype/types/__pycache__/isobmff.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd35125a6d067834526df83407441b1b225bcaee Binary files /dev/null and b/kcweb/utill/filetype/types/__pycache__/isobmff.cpython-36.pyc differ diff --git a/kcweb/utill/filetype/types/__pycache__/video.cpython-36.pyc b/kcweb/utill/filetype/types/__pycache__/video.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6536b3fa42c9a881964e317b602a55c2b0d17ad0 Binary files /dev/null and b/kcweb/utill/filetype/types/__pycache__/video.cpython-36.pyc differ diff --git a/utill/filetype/types/archive.py b/kcweb/utill/filetype/types/archive.py similarity index 100% rename from utill/filetype/types/archive.py rename to kcweb/utill/filetype/types/archive.py diff --git a/utill/filetype/types/audio.py b/kcweb/utill/filetype/types/audio.py similarity index 100% rename from utill/filetype/types/audio.py rename to kcweb/utill/filetype/types/audio.py diff --git a/utill/filetype/types/base.py b/kcweb/utill/filetype/types/base.py similarity index 100% rename from utill/filetype/types/base.py rename to kcweb/utill/filetype/types/base.py diff --git a/utill/filetype/types/font.py b/kcweb/utill/filetype/types/font.py similarity index 100% rename from utill/filetype/types/font.py rename to kcweb/utill/filetype/types/font.py diff --git a/utill/filetype/types/image.py b/kcweb/utill/filetype/types/image.py similarity index 100% rename from utill/filetype/types/image.py rename to kcweb/utill/filetype/types/image.py diff --git a/utill/filetype/types/isobmff.py b/kcweb/utill/filetype/types/isobmff.py similarity index 100% rename from utill/filetype/types/isobmff.py rename to kcweb/utill/filetype/types/isobmff.py diff --git a/utill/filetype/types/video.py b/kcweb/utill/filetype/types/video.py similarity index 100% rename from utill/filetype/types/video.py rename to kcweb/utill/filetype/types/video.py diff --git a/utill/filetype/utils.py b/kcweb/utill/filetype/utils.py similarity index 100% rename from utill/filetype/utils.py rename to kcweb/utill/filetype/utils.py diff --git a/utill/http.py b/kcweb/utill/http.py similarity index 69% rename from utill/http.py rename to kcweb/utill/http.py index e8561bd7b724279db03395f45c2eb9bf8eead97b..9a0b786343ecb83c31f292fceb64612ee646e6e9 100644 --- a/utill/http.py +++ b/kcweb/utill/http.py @@ -7,7 +7,7 @@ class Http: set_proxies=None #设置代理 set_cookies={} #设置请求cookie set_header={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'} #请求头 - set_timeout=10 #超时 20秒 + set_timeout=10 #超时 10秒 set_max_retries=2 #重试次数 (实际请求3次) set_verify=False #SSL 证书的验证 sll证书路径 set_encoding="utf-8" #设置text输出编码 @@ -20,8 +20,31 @@ class Http: get_content='' #获取body响应二进制内容 get_response='' #获取响应对象 get_status_code=None #获取响应状态码 - + keep_alive=True #默认的http connection是keep-alive的 False表示关闭 req=None + def __init(self): + self.set_proxies=None #设置代理 + self.set_cookies={} #设置请求cookie + self.set_header={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'} #请求头 + self.set_timeout=10 #超时 20秒 + self.set_max_retries=2 #重试次数 (实际请求3次) + self.set_verify=False #SSL 证书的验证 sll证书路径 + self.set_encoding="utf-8" #设置text输出编码 + self.set_session=True #是否启用会话 + + self.get_header={} #获取响应头 + self.get_cookies={} #获取最后的响应cookie + self.get_cookie_str='' #获取最后的响应cookie 字符串 + self.get_text='' #获取body响应内容 + self.get_content='' #获取body响应二进制内容 + self.get_response='' #获取响应对象 + self.get_status_code=None #获取响应状态码 + self.keep_alive=True #默认的http connection是keep-alive的 False表示关闭 + self.req=None + def __init__(self): + self.__init() + def __del__(self): + self.__init() def gettext(self): """得到响应text""" return self.get_text @@ -47,11 +70,16 @@ class Http: self.req = requests.Session() self.req.mount('http://', requests.adapters.HTTPAdapter(max_retries=self.set_max_retries)) self.req.mount('https://', requests.adapters.HTTPAdapter(max_retries=self.set_max_retries)) + # print('requests初始化') else: if self.req is None: self.req = requests + # print('requests初始化') + if not self.keep_alive: + self.req.keep_alive=False if self.set_cookies and isinstance(self.set_cookies,str): self.cookieserTdict() + # print(url,url,data,params,jsonparams,self.set_cookies) response=self.req.request(method, url,data=data,params=params,json=jsonparams,files=files,proxies=self.set_proxies,cookies=self.set_cookies,headers=self.set_header,timeout=self.set_timeout,verify=self.set_verify,allow_redirects=allow_redirects) response.encoding=self.set_encoding self.get_header=dict(response.headers) @@ -65,6 +93,8 @@ class Http: if self.get_cookies: cookies='' for key in self.get_cookies: + if not self.get_cookies[key]: + self.get_cookies[key]='' cookies=cookies+key+"="+self.get_cookies[key]+";" self.get_cookie_str=cookies self.get_text=response.text diff --git a/utill/queues.py b/kcweb/utill/queues.py similarity index 97% rename from utill/queues.py rename to kcweb/utill/queues.py index ae6b8c090d97c4f6e2ef074fde13d643a47c2199..c11f3eeb3548317ddb0572ab1c4a01ae6fcd0fd0 100644 --- a/utill/queues.py +++ b/kcweb/utill/queues.py @@ -108,6 +108,12 @@ class Queues(): def delwhere(where): "通过where条件删除 (不推荐使用)" return kcwsqlite.sqlite().connect(queuesdbpath).table("model_kcweb_queues").where(where).delete() + def seltitle(title): + "通过标题查询 (不推荐使用)" + try: + return kcwsqlite.sqlite().connect(queuesdbpath).table("model_kcweb_queues").where("title='"+title+"'").select() + except: + return '' def setfield(taskid,key,value): """设置指定字段(不建议使用)""" try: diff --git a/utill/redis.py b/kcweb/utill/redis.py similarity index 99% rename from utill/redis.py rename to kcweb/utill/redis.py index ba3c1e15cbe8fd695568ec1967e9eeb5a2f47b76..db5a889467729daa20cda8e9fbb6940353b7e1a6 100644 --- a/utill/redis.py +++ b/kcweb/utill/redis.py @@ -28,6 +28,7 @@ class redis: self.__redisObj=red.Redis(host=self.__config['host'],password=self.__config['password'],port=self.__config['port'],db=self.__config['db']) else: self.__redisObj=red.Redis(host=self.__config['host'],port=self.__config['port'],db=self.__config['db']) + if config.app['app_debug']: print("建立redis连接",self.__identifier) @@ -69,7 +70,8 @@ class redis: return self def redisObj(self): "得到一个redis连接对象,执行更多高级操作" - self.__connects() + if not self.__redisObj: + self.__connects() return self.__redisObj def getstr(self,name): """获取name的值 diff --git a/utill/rediss/__init__.py b/kcweb/utill/rediss/__init__.py similarity index 100% rename from utill/rediss/__init__.py rename to kcweb/utill/rediss/__init__.py diff --git a/kcweb/utill/rediss/__pycache__/__init__.cpython-36.pyc b/kcweb/utill/rediss/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c25f98a7d63fded4a0731248bb99c64b1c6f80c6 Binary files /dev/null and b/kcweb/utill/rediss/__pycache__/__init__.cpython-36.pyc differ diff --git a/kcweb/utill/rediss/__pycache__/_compat.cpython-36.pyc b/kcweb/utill/rediss/__pycache__/_compat.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..efde0f6138549c9c6b28c10f9a7c2014742083f2 Binary files /dev/null and b/kcweb/utill/rediss/__pycache__/_compat.cpython-36.pyc differ diff --git a/kcweb/utill/rediss/__pycache__/client.cpython-36.pyc b/kcweb/utill/rediss/__pycache__/client.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eacb05fb13b854f9895ad29aec80643f7f1e6144 Binary files /dev/null and b/kcweb/utill/rediss/__pycache__/client.cpython-36.pyc differ diff --git a/kcweb/utill/rediss/__pycache__/connection.cpython-36.pyc b/kcweb/utill/rediss/__pycache__/connection.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26c19a91523bb17fc00347a542a9c296a34adba3 Binary files /dev/null and b/kcweb/utill/rediss/__pycache__/connection.cpython-36.pyc differ diff --git a/kcweb/utill/rediss/__pycache__/exceptions.cpython-36.pyc b/kcweb/utill/rediss/__pycache__/exceptions.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a04b8fe392d707800ca7a2d9effd3f7d60318fc Binary files /dev/null and b/kcweb/utill/rediss/__pycache__/exceptions.cpython-36.pyc differ diff --git a/kcweb/utill/rediss/__pycache__/lock.cpython-36.pyc b/kcweb/utill/rediss/__pycache__/lock.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..81d948feb06391b381a151d78c3c95ef70913daa Binary files /dev/null and b/kcweb/utill/rediss/__pycache__/lock.cpython-36.pyc differ diff --git a/kcweb/utill/rediss/__pycache__/utils.cpython-36.pyc b/kcweb/utill/rediss/__pycache__/utils.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f70007565a60e40925f0e770411cabb0d5d2626c Binary files /dev/null and b/kcweb/utill/rediss/__pycache__/utils.cpython-36.pyc differ diff --git a/utill/rediss/_compat.py b/kcweb/utill/rediss/_compat.py similarity index 100% rename from utill/rediss/_compat.py rename to kcweb/utill/rediss/_compat.py diff --git a/utill/rediss/client.py b/kcweb/utill/rediss/client.py similarity index 100% rename from utill/rediss/client.py rename to kcweb/utill/rediss/client.py diff --git a/utill/rediss/connection.py b/kcweb/utill/rediss/connection.py similarity index 100% rename from utill/rediss/connection.py rename to kcweb/utill/rediss/connection.py diff --git a/utill/rediss/exceptions.py b/kcweb/utill/rediss/exceptions.py similarity index 100% rename from utill/rediss/exceptions.py rename to kcweb/utill/rediss/exceptions.py diff --git a/utill/rediss/lock.py b/kcweb/utill/rediss/lock.py similarity index 100% rename from utill/rediss/lock.py rename to kcweb/utill/rediss/lock.py diff --git a/utill/rediss/sentinel.py b/kcweb/utill/rediss/sentinel.py similarity index 100% rename from utill/rediss/sentinel.py rename to kcweb/utill/rediss/sentinel.py diff --git a/utill/rediss/utils.py b/kcweb/utill/rediss/utils.py similarity index 100% rename from utill/rediss/utils.py rename to kcweb/utill/rediss/utils.py diff --git a/setup.py b/setup.py index e972b327b53eeebcadad711c35d046f5ed3a17ff..a05dc375f11f8637900a55c84f32a2c487a13c54 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,12 @@ -# python3 setup.py sdist upload -# python setup.py sdist upload +# 打包上传 python setup.py sdist upload +# 打包 python setup.py sdist # twine upload --repository-url https://test.pypi.org/legacy/ dist/* #上传到测试 # pip install --index-url https://pypi.org/simple/ kcweb #安装测试服务上的kcweb pip3 install kcweb==4.12.4 -i https://pypi.org/simple/ +# 安装 python setup.py install ############################################# from setuptools import setup, find_packages,Extension -import os,shutil +import os def file_get_content(k): "获取文件内容" if os.path.isfile(k): @@ -17,14 +18,14 @@ def file_get_content(k): return con confkcw={} confkcw['name']='kcweb' #项目的名称 -confkcw['version']='4.13.26' #项目版本 -confkcw['description']='' #项目的简单描述 -confkcw['long_description']="mysql优化" #项目详细描述 +confkcw['version']='5.328' #项目版本 +confkcw['description']='kcweb作为web开发而设计的高性能框架,采用全新的架构思想,注重易用性。遵循MIT开源许可协议发布,意味着个人和企业可以免费使用kcweb,甚至允许把你基于kcweb开发的应用开源或商业产品发布或销售' #项目的简单描述 +confkcw['long_description']="增加 kcweb 命令" #项目详细描述 confkcw['license']='MIT License' #开源协议 mit开源 confkcw['url']='' -confkcw['author']='禄可集团-坤坤' #名字 +confkcw['author']='坤坤' #名字 confkcw['author_email']='fk1402936534@qq.com' #邮件地址 -confkcw['maintainer']='坤坤' #维护人员的名字 +confkcw['maintainer']='百里' #维护人员的名字 confkcw['maintainer_email']='fk1402936534@qq.com' #维护人员的邮件地址 def get_file(folder='./',lists=[]): lis=os.listdir(folder) @@ -53,8 +54,13 @@ setup( url=confkcw['url'], packages = b, # data_files=[('Scripts', ['kcweb/bin/kcw.exe'])], - install_requires = ['pymongo>=3.10.0','Mako>=1.1.2','requests>=2.23.0','six>=1.12.0','watchdog>=0.9.0','websockets==8.1'], #第三方包 + install_requires = ['gunicorn==20.0.4','pymongo>=3.10.0','Mako>=1.1.2','requests>=2.23.0','six>=1.12.0','watchdog>=0.9.0','websockets==8.1','psutil==5.8.0'], #第三方包 package_data = { '': ['*.html', '*.js','*.css','*.jpg','*.png','*.gif'], + }, + entry_points = { + 'console_scripts':[ + 'kcweb = kcweb.kcweb:executable' + ] } ) \ No newline at end of file diff --git a/utill/db/sqlite copy.py b/utill/db/sqlite copy.py deleted file mode 100644 index ba6140e4864d52bc452e473eb630d9a117debd11..0000000000000000000000000000000000000000 --- a/utill/db/sqlite copy.py +++ /dev/null @@ -1,685 +0,0 @@ -# -*- coding: utf-8 -*- -from kcweb.config import sqlite as sqliteconfig -import time,traceback,re -import random,sqlite3,os,hashlib -class sqlite: - __config=sqliteconfig - __configt={} - __conn={} - __cursor={} - __sql=None - __sqls=None - def md5(self,strs): - """md5加密 - - 参数 strs:要加密的字符串 - - return String类型 - """ - m = hashlib.md5() - b = strs.encode(encoding='utf-8') - m.update(b) - return m.hexdigest() - def close(self): - "关闭连接" - for k in sqlite.__conn.keys(): - sqlite.__cursor[k].close() - sqlite.__conn[k].close() - sqlite.__conn={} - sqlite.__cursor={} - sqlite.__configt={} - def __setconn(self): - if not self.__configt: - self.__configt=sqliteconfig - try: - self.__conn[self.md5(self.__configt['db'])] - except KeyError: - try: - if '/' in self.__configt['db']: - self.__conn[self.md5(self.__configt['db'])] = sqlite3.connect(self.__configt['db'],check_same_thread=False) - else: - self.__conn[self.md5(self.__configt['db'])] = sqlite3.connect(os.path.split(os.path.realpath(__file__))[0]+"/sqlitedata/"+self.__configt['db'],check_same_thread=False) - except Exception as e: - raise Exception(e) - self.__cursor[self.md5(self.__configt['db'])]=self.__conn[self.md5(self.__configt['db'])].cursor() - def __execute(self,typess='DQL'): - self.__setconn() - # print(self.__sql) - try: - res=self.__cursor[self.md5(self.__configt['db'])].execute(self.__sql) - except Exception as e: - - raise Exception(e) - else: - return res - def connect(self,config): - if isinstance(config,str): - self.__configt['db']=config - elif isinstance(config,dict): - if 'db' in config: - self.__configt['db']=config['db'] - return self - __table="" - def table(self,table): - """设置表名 - - 参数 table:str 表名 - """ - self.__table=table - return self - def query(self,sql): - self.__sql=sql - self.__execute(sql,'DQL') - # self.close() - def execute(self,sql): - self.__sql=sql - res=self.__execute('DML') - rowcount=res.rowcount - # self.close() - return rowcount - # def create_table(self): - # self.__sql=("CREATE TABLE "+self.__table+ - # "(ID INT PRIMARY KEY NOT NULL,"+ - # "NAME TEXT NOT NULL,"+ - # "AGE INT NOT NULL,"+ - # "ADDRESS CHAR(50),"+ - # "SALARY REAL);") - # # print(self.__sql) - # # exit() - # self.execute(self.__sql) - def select(self,id=None): - """select查询 - - 返回 list(列表) - """ - if id : - self.__where="id=%d" % id - self.__setsql() - if self.__buildSql: - self.__sqls="("+self.__sql+")" - self.__None() - return self.__sqls - self.__execute() - description=self.__cursor[self.md5(self.__configt['db'])].description #获取字段 - result = self.__cursor[self.md5(self.__configt['db'])].fetchall() #获取查询结果 - # self.close() - lists=[] - data_dict=[] - for field in description:#获取字段 - data_dict.append(field[0]) - for k in result: - i=0 - dicts={} - for j in k: - dicts[data_dict[i]]=j - i=i+1 - lists.append(dicts) - self.__None(table=False) - return lists - def find(self,id=None): - """查询一条记录 - - 返回 字典 - """ - if id : - self.__where="id=%s" % id - self.limit(1) - self.__setsql() - if self.__buildSql: - self.__sqls="("+self.__sql+")" - self.__None() - return self.__sqls - - self.__execute() - description=self.__cursor[self.md5(self.__configt['db'])].description #获取字段 - result = self.__cursor[self.md5(self.__configt['db'])].fetchall() #获取查询结果 - # self.close() - data_dict=[] - for field in description:#获取字段 - data_dict.append(field[0]) - dicts={} - for k in result: - i=0 - for j in k: - dicts[data_dict[i]]=j - i=i+1 - self.__None(table=False) - return dicts - def count(self,field="*"): - """查询数量 - - 返回 int 数字 - """ - self.__field=field - self.__setsql('count') - if self.__buildSql: - self.__sqls="("+self.__sql+")" - return self.__sql - self.__execute() - result = self.__cursor[self.md5(self.__configt['db'])].fetchall() #获取查询结果 - # self.close() - if self.__group: - cou=len(result) - else: - try: - cou=int(result[0][0]) - except IndexError: - cou=0 - self.__None(table=False) - return cou - def max(self,field): - """查询某字段的最大值 - - 返回 int 数字 - """ - self.__field=field - self.__setsql('max') - if self.__buildSql: - self.__sqls="("+self.__sql+")" - return self.__sql - self.__execute() - result = self.__cursor[self.md5(self.__configt['db'])].fetchall() #获取查询结果 - # self.close() - cou=int(result[0][0]) - self.__None(table=False) - return cou - def min(self,field): - """查询某字段的最小值 - - 返回 int 数字 - """ - self.__field=field - self.__setsql('min') - if self.__buildSql: - self.__sqls="("+self.__sql+")" - return self.__sql - self.__execute() - result = self.__cursor[self.md5(self.__configt['db'])].fetchall() #获取查询结果 - # self.close() - cou=int(result[0][0]) - self.__None(table=False) - return cou - def avg(self,field): - """查询某字段的平均值 - - 返回 int 数字 - """ - self.__field=field - self.__setsql('avg') - if self.__buildSql: - self.__sqls="("+self.__sql+")" - return self.__sql - self.__execute() - result = self.__cursor[self.md5(self.__configt['db'])].fetchall() #获取查询结果 - # self.close() - cou=int(result[0][0]) - self.__None(table=False) - return cou - def sum(self,field): - """查询某字段之和 - - 返回 int 数字 - """ - self.__field=field - self.__setsql('sum') - if self.__buildSql: - self.__sqls="("+self.__sql+")" - return self.__sql - self.__execute() - result = self.__cursor[self.md5(self.__configt['db'])].fetchall() #获取查询结果 - # self.close() - cou=int(result[0][0]) - self.__None(table=False) - return cou - def update(self,data,affair=False): - """数据表更新 - - 参数 data 要更新的内容 格式:{"name":"测试","age":20} - - 参数 affair 是否开启事务 True表示手动提交事务 False表示自动提交事务 - """ - self.__setsql('update',data) - res=self.__execute('DML') - if affair==False and self.__startTrans==False: - self.commit() - rowcount=res.rowcount - # self.close() - self.__None(table=False) - return rowcount - def delete(self,affair=False): - """数据表删除 - - 参数 affair 是否开启事务 True表示手动提交事务 False表示自动提交事务 - """ - self.__setsql('delete') - if self.__where: - res=self.__execute('DML') - else: - return 0 - if affair==False and self.__startTrans==False: - self.commit() - rowcount=res.rowcount - # self.close() - self.__None(table=False) - return rowcount - def insert(self,dicts,affair=False): - """插入数据库 单条插入或多条插入 - - 参数 dicts 要插入的内容 单条格式:{"name":"测试","age":20} 。 多条格式:[{"name":"测试","age":20},{"name":"测试","age":20}] - - 参数 affair 是否开启事务 True表示手动提交事务 False表示自动提交事务 - - 返回插入的数量 - """ - self.__setsql('insert',dicts) - res=self.__execute('DML') - if affair==False and self.__startTrans==False: - self.commit() - rowcount=res.rowcount - # self.close() - self.__None(table=False) - return rowcount - __startTrans=False - def startTrans(self): - "开启事务,仅对 update方法、delete方法、install方法有效" - self.__startTrans=True - def commit(self): - """事务提交 - - 增删改后的任务进行提交 - """ - self.__conn[self.md5(self.__configt['db'])].commit() - def rollback(self): - """事务回滚 - - 增删改后的任务进行撤销 - """ - self.__conn[self.md5(self.__configt['db'])].rollback() - def getsql(self): - """得到生成的sql语句""" - return self.__sql - __buildSql=None - def buildSql(self): - """构造子查询""" - self.__buildSql=True - return self - def __None(self,table=True): - "清除所有赋值条件" - self.__lock=None - self.__distinct=None - self.__join=None - self.__joinstr='' - self.__alias=None - self.__having=None - self.__group=None - self.__group1=None - self.__order=None - self.__order1=None - self.__limit=None - self.__field="*" - self.__where=None - self.__wheres=() - self.__buildSql=None - if table: - self.__table=None - __where=None - __wheres=() - def where(self,where = None,*wheres): - """设置过滤条件 - - 传入方式: - "id",2 表示id='2' - - "id","in",2,3,4,5,6,...表示 id in (2,3,4,5,6,...) - - "id","in",[2,3,4,5,6,...]表示 id in (2,3,4,5,6,...) - - [("id","gt",6000),"and",("name","like","%超")] 表示 ( id > "6000" and name LIKE "%超" ) - - "id","eq",1 表示 id = '1' - - eq 等于 - neq 不等于 - gt 大于 - egt 大于等于 - lt 小于 - elt 小于等于 - like LIKE - """ - self.__where=where - self.__wheres=wheres - # print(len(self.__wheres)) - return self - __field='*' - def field(self,field = "*"): - """设置过滤显示条件 - - 参数 field:str 字符串 - """ - self.__field=field - return self - __limit=[] - def limit(self,offset, length = None): - """设置查询数量 - - 参数 offset:int 起始位置 - - 参数 length:int 查询数量 - """ - self.__limit=[offset,length] - return self - def page(self,pagenow=1, length = 20): - """设置分页查询 - - 参数 pagenow:int 页码 - - 参数 length:int 查询数量 - """ - offset=(pagenow-1)*length - self.__limit=[offset,length] - return self - __order=None - __order1=None - def order(self,strs=None,*strs1): - """设置排序查询 - - 传入方式: - - "id desc" - - "id",'name','appkey','asc' - - "id",'name','appkey' 不包含asc或desc的情况下 默认是desc - - ['id','taskid',{"task_id":"desc"}] - """ - self.__order=strs - self.__order1=strs1 - return self - __group=None - __group1=None - def group(self,strs=None,*strs1): - """设置分组查询 - - 传入方式: - - "id,name" - - "id","name" - """ - self.__group=strs - self.__group1=strs1 - return self - __having=None - def having(self,strs=None): - """用于配合group方法完成从分组的结果中筛选(通常是聚合条件)数据 - - 参数 strs:string 如:"count(time)>3" - """ - self.__having=strs - return self - - __alias=None - def alias(self,strs=None): - """用于设置当前数据表的别名,便于使用其他的连贯操作例如join方法等。 - - 参数 strs:string 默认当前表作为别名 - """ - if strs: - self.__alias=strs - else: - self.__alias=self.__table - return self - __join=None - __joinstr='' - def join(self,strs,on=None,types='INNER'): - """用于根据两个或多个表中的列之间的关系,从这些表中查询数据 - - 参数 strs string 如:"test t1" test表设置别名t1 - - 参数 on string 如:"t1.id=t2.pid" 设置连接条件 - - 参数 types 支持INNER、LEFT、RIGHT、FULL 默认INNER - - """ - joinstr='' - if strs and on: - joinstr=joinstr+types+" JOIN "+strs+" ON "+on+" " - if joinstr: - self.__joinstr=self.__joinstr+joinstr - return self - __distinct=None - def distinct(self,bools=None): - "用于返回唯一不同的值,配合field方法使用生效,消除所有重复的记录,并只获取唯一一次记录。" - self.__distinct=bools - return self - __lock=None - def lock(self,strs=None): - """用于数据库的锁机制,在查询或者执行操作的时候使用 (暂未实现) - - 排他锁 (Exclusive lock) - - 共享锁 (Shared lock) - - 参数 strs 如:True表示自动在生成的SQL语句最后加上FOR UPDATE, - - - """ - # self.__lock=strs - return self - def __setsql(self,types=None,data = {}): - """生成sql语句""" - if types==None: - self.__sql="SELECT" - if self.__distinct and self.__field: - self.__sql=self.__sql+" DISTINCT" - if self.__alias: - self.__sql=self.__sql+" %s FROM %s %s" % (self.__field,self.__table,self.__alias) - else: - self.__sql=self.__sql+" %s FROM %s" % (self.__field,self.__table) - elif types=='count': - self.__sql="SELECT COUNT(%s) FROM %s" % (self.__field,self.__table) - elif types=='max': - self.__sql="SELECT MAX(%s) FROM %s" % (self.__field,self.__table) - elif types=='min': - self.__sql="SELECT MIN(%s) FROM %s" % (self.__field,self.__table) - elif types=='avg': - self.__sql="SELECT AVG(%s) FROM %s" % (self.__field,self.__table) - elif types=='sum': - self.__sql="SELECT SUM(%s) FROM %s" % (self.__field,self.__table) - elif types=='update': - strs='' - for k in data: - if isinstance(data[k],str): - strs=strs+" %s = '%s' ," % (k,self.escape_string(data[k])) - else: - strs=strs+" %s = %s ," % (k,data[k]) - strs=strs[:-1] - self.__sql="UPDATE %s SET %s" % (self.__table,strs) - # print(self.__sql) - elif types=='delete': - self.__sql="DELETE FROM %s" % (self.__table) - elif types=='insert': - if isinstance(data,dict): - strs='' - val='' - for k in data: - strs=strs+"%s," % k - if isinstance(data[k],str): - val=val+"'%s'," % self.escape_string(data[k]) - else: - val=val+"%s," % data[k] - strs=strs[:-1] - val=val[:-1] - self.__sql="INSERT INTO "+str(self.__table)+" ("+strs+") VALUES ("+val+")" - # print(self.__sql) - elif isinstance(data,list): - strs='' - val='(' - for k in data[0]: - strs=strs+" , "+k - for k in data: - for j in k: - if isinstance(k[j],str): - val=val+"'"+str(k[j])+"'," - else: - val=val+str(k[j])+"," - val=val[:-1] - val=val+"),(" - val=val[:-2] - self.__sql="INSERT INTO "+str(self.__table)+" ("+strs[3:]+") VALUES "+val - - if self.__joinstr: - # print(self.__sql) - self.__sql=self.__sql+" "+self.__joinstr - if self.__where: - if isinstance(self.__where,str): - if self.__wheres: - if len(self.__wheres) == 2: - if isinstance(self.__wheres[1],list): - self.__sql=self.__sql + " WHERE %s %s (" % (self.__where,self.__operator(self.__wheres[0])) - for k in self.__wheres[1]: - self.__sql=self.__sql+str(k)+"," - self.__sql=self.__sql[:-1]+")" - else: - self.__sql=self.__sql + " WHERE %s %s '%s'" % (self.__where,self.__operator(self.__wheres[0]),self.__wheres[1]) - elif len(self.__wheres) > 2: - if self.__wheres[0]=='in': - strs=str(self.__wheres[1]) - i=0 - for k in self.__wheres: - if i > 1: - strs=strs+","+str(k) - i=i+1 - self.__sql=self.__sql + " WHERE %s in (%s)" % (self.__where,strs) - else: - self.__sql=self.__sql + " WHERE %s = '%s'" % (self.__where,self.__wheres[0]) - else: - self.__sql=self.__sql + " WHERE %s" % self.__where - elif isinstance(self.__where,list): - self.__sql=self.__sql + " WHERE %s" % self.__listTrans() - else: - print("参数where类型错误",type(self.__where),self.__where) - if self.__order: - s='' - if isinstance(self.__order,list): - for strs in self.__order: - if isinstance(strs,str): - s=s+strs+"," - else: - pass - for key in strs: - s=s+key+" "+strs[key] - s=s+"," - s=s[:-1] - if isinstance(self.__order,str): - if self.__order1: - if len(self.__order1) > 1: - if self.__order1[len(self.__order1)-1] == 'desc' or self.__order1[len(self.__order1)-1] == 'asc': - i=0 - while i