no history
This commit is contained in:
commit
fe7212ae67
133
README.md
Executable file
133
README.md
Executable file
@ -0,0 +1,133 @@
|
||||
# SQLOR
|
||||
|
||||
SQLOR is a database api for python3, it is base on the python's DBAPI2
|
||||
|
||||
## Features
|
||||
|
||||
* Multiple database supported(Oracle, MySql, Postgresql, SQL Server
|
||||
* Both asynchronous API & synchronous API supported
|
||||
* Connection pools
|
||||
* Connection life cycle managements
|
||||
* Easy using API
|
||||
* Resources(connection object, cursor object) automatic recycled
|
||||
|
||||
|
||||
## requirements
|
||||
|
||||
* python 3.5 or above
|
||||
* asyncio
|
||||
* Oracle DBAPI2 driver(cx_Oracle)
|
||||
* MySQL DBAPI2 driver(mysql-connector)
|
||||
* Postgresql DBAPI2 driver(psycopg2-binrary)
|
||||
* Asynchronous MySQL driver(aiomysql)
|
||||
* Asynchronous Postgresql driver(aiopg)
|
||||
* Other driver can be easy integreated
|
||||
|
||||
## Using
|
||||
|
||||
```
|
||||
import asyncio
|
||||
|
||||
from sqlor.dbpools import DBPools
|
||||
|
||||
dbs={
|
||||
"aiocfae":{
|
||||
"driver":"aiomysql",
|
||||
"async_mode":True,
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"stock":{
|
||||
"driver":"aiopg",
|
||||
"async_mode":True,
|
||||
"codeing":"utf-8",
|
||||
"dbname":"stock",
|
||||
"kwargs":{
|
||||
"dbname":"stock",
|
||||
"user":"test",
|
||||
"password":"test123",
|
||||
"host":"127.0.0.1"
|
||||
}
|
||||
},
|
||||
"cfae":{
|
||||
"driver":"mysql.connector",
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
pool = DBPools(dbs,loop=loop)
|
||||
|
||||
async def testfunc():
|
||||
@pool.runSQL
|
||||
def sql(db,ns,callback):
|
||||
return {
|
||||
"sql_string":"select * from product",
|
||||
}
|
||||
x = await sql('cfae',{},print)
|
||||
x = await sql('aiocfae',{},print)
|
||||
|
||||
loop.run_until_complete(testfunc())
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
|
||||
### Databases description data(dbdesc)
|
||||
|
||||
sqlor uses a dbdesc data(databases description data) which description
|
||||
how many databases and what database will using, and them connection parameters to create a dbpools objects
|
||||
|
||||
dbdesc data is a dict data, format of the dbdesc as follow:
|
||||
```
|
||||
{
|
||||
"aiocfae":{ # name to identify a database connect
|
||||
"driver":"aiomysql", # database dbapi2 driver package name
|
||||
"async_mode":True, # indicte this connection is asynchronous mode
|
||||
"coding":"utf8", # charset coding
|
||||
"dbname":"cfae", # database real name
|
||||
"kwargs":{ # connection parameters
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"cfae":{
|
||||
"driver":"mysql.connector",
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
sqlor can using multiple databases and difference databases by using difference database driver
|
||||
|
||||
### sql description data
|
||||
|
||||
|
||||
## class
|
||||
|
||||
### DBPools
|
||||
|
||||
### SQLor
|
||||
|
4
build.sh
Executable file
4
build.sh
Executable file
@ -0,0 +1,4 @@
|
||||
rm dist/*.whl
|
||||
python setup.py install
|
||||
python setup.py bdist_wheel
|
||||
python -m twine upload --repository-url https://upload.pypi.org/legacy/ dist/*.whl
|
0
build/lib/sqlor/__init__.py
Normal file
0
build/lib/sqlor/__init__.py
Normal file
7
build/lib/sqlor/aiomysqlor.py
Normal file
7
build/lib/sqlor/aiomysqlor.py
Normal file
@ -0,0 +1,7 @@
|
||||
from .mysqlor import MySqlor
|
||||
|
||||
class AioMysqlor(MySqlor):
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='aiomysql'
|
||||
|
10
build/lib/sqlor/aiopostgresqlor.py
Normal file
10
build/lib/sqlor/aiopostgresqlor.py
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
from .postgresqlor import PostgreSQLor
|
||||
class AioPostgresqlor(PostgreSQLor):
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='aiopg'
|
||||
|
||||
async def commit(self):
|
||||
pass
|
||||
|
7
build/lib/sqlor/aiosqliteor.py
Normal file
7
build/lib/sqlor/aiosqliteor.py
Normal file
@ -0,0 +1,7 @@
|
||||
import re
|
||||
from .sqlite3or import SQLite3or
|
||||
|
||||
class Aiosqliteor(SQLite3or):
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='aiosqlite'
|
1
build/lib/sqlor/const.py
Normal file
1
build/lib/sqlor/const.py
Normal file
@ -0,0 +1 @@
|
||||
ROWS=100
|
373
build/lib/sqlor/crud.py
Normal file
373
build/lib/sqlor/crud.py
Normal file
@ -0,0 +1,373 @@
|
||||
# -*- coding:utf8 -*-
|
||||
from .dbpools import DBPools
|
||||
from .const import ROWS
|
||||
from .filter import DBFilter
|
||||
from appPublic.objectAction import ObjectAction
|
||||
from appPublic.dictObject import DictObject
|
||||
from appPublic.timeUtils import date2str,time2str,str2Date
|
||||
from appPublic.uniqueID import getID
|
||||
toStringFuncs={
|
||||
'char':None,
|
||||
'str':None,
|
||||
'short':str,
|
||||
'long':str,
|
||||
'float':str,
|
||||
'date':date2str,
|
||||
'time':time2str,
|
||||
}
|
||||
fromStringFuncs={
|
||||
'short':int,
|
||||
'long':int,
|
||||
'float':float,
|
||||
'date':str2Date,
|
||||
'time':str2Date
|
||||
}
|
||||
|
||||
class DatabaseNotfound(Exception):
|
||||
def __init__(self,dbname):
|
||||
Exception.__init__(self)
|
||||
self.dbname = dbname
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.dbname} not found'
|
||||
|
||||
class CRUD(object):
|
||||
def __init__(self,dbname,tablename,rows=ROWS):
|
||||
self.pool = DBPools()
|
||||
if dbname not in self.pool.databases.keys():
|
||||
raise DatabaseNotfound(dbname)
|
||||
self.dbname = dbname
|
||||
self.tablename = tablename
|
||||
self.rows = rows
|
||||
self.primary_data = None
|
||||
self.oa = ObjectAction()
|
||||
|
||||
async def primaryKey(self,**kw):
|
||||
if self.primary_data is None:
|
||||
self.primary_data = await self.pool.getTablePrimaryKey(self.dbname,
|
||||
self.tablename,**kw)
|
||||
|
||||
return self.primary_data
|
||||
|
||||
async def forignKeys(self,**kw):
|
||||
data = self.pool.getTableForignKeys(self.dbname,self.tablename,**kw)
|
||||
return data
|
||||
|
||||
async def I(self,**kw):
|
||||
"""
|
||||
fields information
|
||||
"""
|
||||
@self.pool.inSqlor
|
||||
async def main(dbname,NS,**kw):
|
||||
pkdata = await self.primaryKey(**kw)
|
||||
pks = [ i.field_name for i in pkdata ]
|
||||
data = await self.pool.getTableFields(self.dbname,self.tablename,**kw)
|
||||
for d in data:
|
||||
if d.name in pks:
|
||||
d.update({'primarykey':True})
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'tableInfo',data)
|
||||
return data
|
||||
|
||||
return await main(self.dbname,{},**kw)
|
||||
|
||||
async def fromStr(self,data):
|
||||
fields = await self.pool.getTableFields(self.dbname,self.tablename)
|
||||
ret = {}
|
||||
for k in data:
|
||||
v = None if data[k] == '' else data[k]
|
||||
for f in fields:
|
||||
if k == f.name:
|
||||
ret[k] = v
|
||||
f = fromStringFuncs.get(f.type,None)
|
||||
if f is not None and v is not None:
|
||||
ret[k] = f(v)
|
||||
return ret
|
||||
|
||||
async def toStr(self,data):
|
||||
fields = await self.pool.getTableFields(self.dbname,self.tablename)
|
||||
ret = {}
|
||||
for k in data:
|
||||
for f in fields:
|
||||
if k == f.name:
|
||||
ret[k] = data[k]
|
||||
f = toStringFuncs.get(f.type,None)
|
||||
if f is not None and data[k] is not None:
|
||||
ret[k] = f(data[k])
|
||||
return ret
|
||||
|
||||
async def datagrid(self,request,targeti,**kw):
|
||||
fields = await self.I()
|
||||
fs = [ self.defaultIOField(f) for f in fields ]
|
||||
id = self.dbname+':'+ self.tablename
|
||||
pk = await self.primaryKey(**kw)
|
||||
idField = pk[0]['field_name']
|
||||
data = {
|
||||
"tmplname":"widget_js.tmpl",
|
||||
"data":{
|
||||
"__ctmpl__":"datagrid",
|
||||
"__target__":target,
|
||||
"data":{
|
||||
"name":id,
|
||||
"icon-conv":"icon-table",
|
||||
"title":tablename,
|
||||
"url":absurl('./RP.dspy?id=%s' % id),
|
||||
"deleteUrl":absurl('./D.dspy?id=%s' % id),
|
||||
"addUrl":absurl('./C.dspy?id=%s' % id),
|
||||
"updateUrl":absurl('./U.dspy?id=%s' % id),
|
||||
"idField":idField,
|
||||
"dnd":True,
|
||||
"view":"scrollview",
|
||||
"fields":fs,
|
||||
"toolbar":{
|
||||
"tools":[
|
||||
{
|
||||
"name":"add",
|
||||
"icon":"icon-add",
|
||||
"label":"add ball"
|
||||
},
|
||||
{
|
||||
"name":"delete",
|
||||
"icon":"icon-delete",
|
||||
"label":"delete ball"
|
||||
},
|
||||
{
|
||||
"name":"moveup",
|
||||
"icon":"icon-up",
|
||||
"label":"moveup ball"
|
||||
},
|
||||
{
|
||||
"name":"movedown",
|
||||
"icon":"icon-down",
|
||||
"label":"movedown ball"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options":{
|
||||
"pageSize":50,
|
||||
"pagination":False
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data = self.oa.execute(id,'datagrid',data)
|
||||
return data
|
||||
|
||||
def defaultIOField(self,f):
|
||||
if f.type in ['str']:
|
||||
return {
|
||||
"primarykey":f.get('primarykey',False),
|
||||
"name":f.name,
|
||||
"hidden":False,
|
||||
"sortable":True,
|
||||
"label":f.title,
|
||||
"align":"center",
|
||||
"iotype":"text"
|
||||
}
|
||||
if f.type in ['float','short','long']:
|
||||
return {
|
||||
"primarykey":f.get('primarykey',False),
|
||||
"sortable":True,
|
||||
"name":f.name,
|
||||
"hidden":False,
|
||||
"label":f.title,
|
||||
"align":"right",
|
||||
"iotype":"text"
|
||||
}
|
||||
return {
|
||||
"primarykey":f.get('primarykey',False),
|
||||
"name":f.name,
|
||||
"sortable":True,
|
||||
"hidden":False,
|
||||
"label":f.title,
|
||||
"align":"center",
|
||||
"iotype":"text"
|
||||
}
|
||||
|
||||
async def C(self,rec,**kw):
|
||||
"""
|
||||
create new data
|
||||
"""
|
||||
@self.pool.runSQL
|
||||
async def addSQL(dbname,data,**kw):
|
||||
fns = kw['fns']
|
||||
vfs = kw['vfs']
|
||||
sqldesc={
|
||||
"sql_string" : """
|
||||
insert into %s (%s) values (%s)
|
||||
""" % (self.tablename,fns,vfs),
|
||||
}
|
||||
return sqldesc
|
||||
|
||||
@self.pool.inSqlor
|
||||
async def main(dbname,NS,**kw):
|
||||
fields = await self.pool.getTableFields(self.dbname,self.tablename,**kw)
|
||||
flist = [ f['name'] for f in fields ]
|
||||
fns = ','.join(flist)
|
||||
vfs = ','.join([ '${' + f + '}$' for f in flist ])
|
||||
data = {}
|
||||
[ data.update({k.lower():v}) for k,v in NS.items() ]
|
||||
pk = await self.primaryKey(**kw)
|
||||
k = pk[0]['field_name']
|
||||
if not data.get(k):
|
||||
v = getID()
|
||||
data[k] = v
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'beforeAdd',data)
|
||||
kwargs = kw.copy()
|
||||
kwargs['fns'] = fns
|
||||
kwargs['vfs'] = vfs
|
||||
await addSQL(self.dbname,data,**kwargs)
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'afterAdd',data)
|
||||
return {k:data[k]}
|
||||
|
||||
return await main(self.dbname,rec,**kw)
|
||||
|
||||
async def defaultFilter(self,NS,**kw):
|
||||
fields = await self.pool.getTableFields(self.dbname,self.tablename,**kw)
|
||||
d = [ '%s = ${%s}$' % (f['name'],f['name']) for f in fields if f['name'] in NS.keys() ]
|
||||
if len(d) == 0:
|
||||
return ''
|
||||
ret = ' and ' + ' and '.join(d)
|
||||
return ret
|
||||
|
||||
async def R(self,filters=None,NS={},**kw):
|
||||
"""
|
||||
retrieve data
|
||||
"""
|
||||
@self.pool.runSQL
|
||||
async def retrieve(dbname,data,**kw):
|
||||
fstr = ''
|
||||
if filters is not None:
|
||||
fstr = ' and '
|
||||
dbf = DBFilter(filters)
|
||||
fstr = fstr + dbf.genFilterString()
|
||||
else:
|
||||
fstr = await self.defaultFilter(NS,**kw)
|
||||
sqldesc = {
|
||||
"sql_string":"""select * from %s where 1=1 %s""" % (self.tablename,fstr),
|
||||
}
|
||||
return sqldesc
|
||||
|
||||
@self.pool.runSQLPaging
|
||||
async def pagingdata(dbname,data,filters=None,**kw):
|
||||
fstr = ""
|
||||
if filters is not None:
|
||||
fstr = ' and '
|
||||
dbf = DBFilter(filters)
|
||||
fstr = fstr + dbf.genFilterString()
|
||||
else:
|
||||
fstr = await self.defaultFilter(NS,**kw)
|
||||
|
||||
sqldesc = {
|
||||
"sql_string":"""select * from %s where 1=1 %s""" % (self.tablename,fstr),
|
||||
"default":{'rows':self.rows}
|
||||
}
|
||||
return sqldesc
|
||||
|
||||
@self.pool.inSqlor
|
||||
async def main(dbname,NS,**kw):
|
||||
p = await self.primaryKey(**kw)
|
||||
if NS.get('__id') is not None:
|
||||
NS[p[0]['field_name']] = NS['__id']
|
||||
del NS['__id']
|
||||
if NS.get('page'):
|
||||
del NS['page']
|
||||
|
||||
if NS.get('page'):
|
||||
if NS.get('sort',None) is None:
|
||||
NS['sort'] = p[0]['field_name']
|
||||
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'beforeRetrieve',NS)
|
||||
if NS.get('page'):
|
||||
data = await pagingdata(self.dbname,data,**kw)
|
||||
else:
|
||||
data = await retrieve(self.dbname,data,**kw)
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'afterRetrieve',data)
|
||||
return data
|
||||
|
||||
return await main(self.dbname,NS,**kw)
|
||||
|
||||
async def U(self,data, **kw):
|
||||
"""
|
||||
update data
|
||||
"""
|
||||
@self.pool.runSQL
|
||||
async def update(dbname,NS,**kw):
|
||||
condi = [ i['field_name'] for i in self.primary_data ]
|
||||
newData = [ i for i in NS.keys() if i not in condi ]
|
||||
c = [ '%s = ${%s}$' % (i,i) for i in condi ]
|
||||
u = [ '%s = ${%s}$' % (i,i) for i in newData ]
|
||||
cs = ' and '.join(c)
|
||||
us = ','.join(u)
|
||||
sqldesc = {
|
||||
"sql_string":"""update %s set %s where %s""" % (self.tablename,us,cs)
|
||||
}
|
||||
return sqldesc
|
||||
|
||||
@self.pool.inSqlor
|
||||
async def main(dbname,NS,**kw):
|
||||
pk = await self.primaryKey(**kw)
|
||||
pkfields = [k.field_name for k in pk ]
|
||||
newData = [ k for k in data if k not in pkfields ]
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'beforeUpdate',data)
|
||||
await update(self.dbname,data,**kw)
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'afterUpdate',data)
|
||||
return data
|
||||
return await main(self.dbname,data,**kw)
|
||||
|
||||
async def D(self,data,**kw):
|
||||
"""
|
||||
delete data
|
||||
"""
|
||||
@self.pool.runSQL
|
||||
def delete(dbname,data,**kw):
|
||||
pnames = [ i['field_name'] for i in self.primary_data ]
|
||||
c = [ '%s = ${%s}$' % (i,i) for i in pnames ]
|
||||
cs = ' and '.join(c)
|
||||
sqldesc = {
|
||||
"sql_string":"delete from %s where %s" % (self.tablename,cs)
|
||||
}
|
||||
return sqldesc
|
||||
|
||||
@self.pool.inSqlor
|
||||
async def main(dbname,NS,**kw):
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'beforeDelete',data)
|
||||
await delete(self.dbname,data,pkfields,**kw)
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'afterDelete',data)
|
||||
return data
|
||||
return await main(self.dbname,data,**kw)
|
||||
|
||||
if __name__ == '__main__':
|
||||
DBPools({
|
||||
"ambi":{
|
||||
"driver":"pymssql",
|
||||
"coding":"utf-8",
|
||||
"dbname":"ambi",
|
||||
"kwargs":{
|
||||
"user":"ymq",
|
||||
"database":"ambi",
|
||||
"password":"ymq123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"metadb":{
|
||||
"driver":"pymssql",
|
||||
"coding":"utf-8",
|
||||
"dbname":"metadb",
|
||||
"kwargs":{
|
||||
"user":"ymq",
|
||||
"database":"metadb",
|
||||
"password":"ymq123",
|
||||
"host":"localhost"
|
||||
}
|
||||
}
|
||||
})
|
||||
crud = CRUD('ambi')
|
||||
#fields = crud.I('cashflow')
|
||||
#for i in fields:
|
||||
# print(i)
|
||||
|
||||
data = crud.RP('cashflow')
|
||||
print(data.total)
|
||||
for i in data.rows:
|
||||
print(i.balance,i.asid)
|
||||
|
493
build/lib/sqlor/dbpools.py
Normal file
493
build/lib/sqlor/dbpools.py
Normal file
@ -0,0 +1,493 @@
|
||||
|
||||
import asyncio
|
||||
from traceback import print_exc
|
||||
from functools import wraps
|
||||
import codecs
|
||||
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from appPublic.myImport import myImport
|
||||
from appPublic.dictObject import DictObject
|
||||
from appPublic.Singleton import SingletonDecorator
|
||||
from appPublic.myjson import loadf
|
||||
from appPublic.jsonConfig import getConfig
|
||||
from appPublic.rc4 import unpassword
|
||||
|
||||
import threading
|
||||
from .sor import SQLor
|
||||
from .mssqlor import MsSqlor
|
||||
from .oracleor import Oracleor
|
||||
from .sqlite3or import SQLite3or
|
||||
from .aiosqliteor import Aiosqliteor
|
||||
from .mysqlor import MySqlor
|
||||
from .aiomysqlor import AioMysqlor
|
||||
from .aiopostgresqlor import AioPostgresqlor
|
||||
|
||||
def sqlorFactory(dbdesc):
|
||||
driver = dbdesc.get('driver',dbdesc)
|
||||
def findSubclass(name,klass):
|
||||
for k in klass.__subclasses__():
|
||||
if k.isMe(name):
|
||||
return k
|
||||
k1 = findSubclass(name,k)
|
||||
if k1 is not None:
|
||||
return k1
|
||||
return None
|
||||
k = findSubclass(driver,SQLor)
|
||||
if k is None:
|
||||
return SQLor(dbdesc=dbdesc)
|
||||
return k(dbdesc=dbdesc)
|
||||
|
||||
def sqlorFromFile(dbdef_file,coding='utf8'):
|
||||
dbdef = loadf(dbdef_file)
|
||||
return sqlorFactory(dbdef)
|
||||
|
||||
class LifeConnect:
|
||||
def __init__(self,connfunc,kw,use_max=1000,async_mode=False):
|
||||
self.connfunc = connfunc
|
||||
self.async_mode = async_mode
|
||||
self.use_max = use_max
|
||||
self.kw = kw
|
||||
self.conn = None
|
||||
self.used = False
|
||||
|
||||
def print(self):
|
||||
print(self.use_max)
|
||||
print(self.conn)
|
||||
|
||||
async def _mkconn(self):
|
||||
if self.async_mode:
|
||||
self.conn = await self.connfunc(**self.kw)
|
||||
else:
|
||||
self.conn = self.connfunc(**self.kw)
|
||||
self.use_cnt = 0
|
||||
|
||||
async def use(self):
|
||||
if self.conn is None:
|
||||
await self._mkconn()
|
||||
wait_time = 0.2
|
||||
loop_cnt = 4
|
||||
while loop_cnt > 0:
|
||||
if await self.testok():
|
||||
return self.conn
|
||||
await asyncio.sleep(wait_time)
|
||||
wait_time = wait_time + 0.4
|
||||
loop_cnt = loop_cnt - 1
|
||||
try:
|
||||
await self.conn.close()
|
||||
except:
|
||||
pass
|
||||
self.conn = None
|
||||
await self._mkconn()
|
||||
raise Exception('database connect break')
|
||||
|
||||
async def free(self,conn):
|
||||
self.use_cnt = self.use_cnt + 1
|
||||
return
|
||||
if self.use_cnt >= self.use_max:
|
||||
await self.conn.close()
|
||||
await self._mkcomm()
|
||||
|
||||
async def testok(self):
|
||||
if self.async_mode:
|
||||
async with self.conn.cursor() as cur:
|
||||
try:
|
||||
await cur.execute('select 1 as cnt')
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
else:
|
||||
cur = self.conn.cursor()
|
||||
try:
|
||||
cur.execute('select 1 as cnt')
|
||||
r = cur.fetchall()
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
finally:
|
||||
cur.close()
|
||||
|
||||
class ConnectionPool(object):
|
||||
def __init__(self,dbdesc,loop):
|
||||
self.dbdesc = dbdesc
|
||||
self.async_mode = dbdesc.get('async_mode',False)
|
||||
self.loop = loop
|
||||
self.driver = myImport(self.dbdesc['driver'])
|
||||
self.maxconn = dbdesc.get('maxconn',5)
|
||||
self.maxuse = dbdesc.get('maxuse',1000)
|
||||
self._pool = asyncio.Queue(self.maxconn)
|
||||
self.connectObject = {}
|
||||
self.use_cnt = 0
|
||||
self.max_use = 1000
|
||||
# self.lock = asyncio.Lock()
|
||||
# self.lockstatus()
|
||||
|
||||
def lockstatus(self):
|
||||
return
|
||||
self.loop.call_later(5,self.lockstatus)
|
||||
print('--lock statu=',self.lock.locked(),
|
||||
'--pool empty()=',self._pool.empty(),
|
||||
'--full()=',self._pool.full()
|
||||
)
|
||||
|
||||
async def _fillPool(self):
|
||||
for i in range(self.maxconn):
|
||||
lc = await self.connect()
|
||||
i = i + 1
|
||||
|
||||
async def connect(self):
|
||||
lc = LifeConnect(self.driver.connect,self.dbdesc['kwargs'],
|
||||
use_max=self.maxuse,async_mode=self.async_mode)
|
||||
await self._pool.put(lc)
|
||||
return lc
|
||||
|
||||
def isEmpty(self):
|
||||
return self._pool.empty()
|
||||
|
||||
def isFull(self):
|
||||
return self._pool.full()
|
||||
|
||||
async def aquire(self):
|
||||
lc = await self._pool.get()
|
||||
conn = await lc.use()
|
||||
"""
|
||||
with await self.lock:
|
||||
self.connectObject[lc.conn] = lc
|
||||
"""
|
||||
self.connectObject[lc.conn] = lc
|
||||
return conn
|
||||
|
||||
async def release(self,conn):
|
||||
lc = None
|
||||
"""
|
||||
with await self.lock:
|
||||
lc = self.connectObject.get(conn,None)
|
||||
del self.connectObject[conn]
|
||||
"""
|
||||
lc = self.connectObject.get(conn,None)
|
||||
del self.connectObject[conn]
|
||||
await self._pool.put(lc)
|
||||
|
||||
@SingletonDecorator
|
||||
class DBPools:
|
||||
def __init__(self,databases={},max_connect=100,loop=None):
|
||||
if loop is None:
|
||||
loop = asyncio.get_event_loop()
|
||||
self.loop = loop
|
||||
self.max_connect = max_connect
|
||||
self.sema = asyncio.Semaphore(max_connect)
|
||||
self._cpools = {}
|
||||
self.databases = databases
|
||||
self.meta = {}
|
||||
|
||||
def get_dbname(self, name):
|
||||
desc = self.database.get(name)
|
||||
if not desc:
|
||||
return None
|
||||
return desc.get('dbname')
|
||||
|
||||
def addDatabase(self,name,desc):
|
||||
self.databases[name] = desc
|
||||
|
||||
async def getSqlor(self,name):
|
||||
await self.sema.acquire()
|
||||
desc = self.databases.get(name)
|
||||
sor = sqlorFactory(desc)
|
||||
sor.name = name
|
||||
a,conn,cur = await self._aquireConn(name)
|
||||
sor.setCursor(a,conn,cur)
|
||||
return sor
|
||||
|
||||
async def freeSqlor(self,sor):
|
||||
await self._releaseConn(sor.name,sor.conn,sor.cur)
|
||||
self.sema.release()
|
||||
|
||||
@asynccontextmanager
|
||||
async def sqlorContext(self,name):
|
||||
sqlor = await self.getSqlor(name)
|
||||
try:
|
||||
yield sqlor
|
||||
except Exception as e:
|
||||
print_exc()
|
||||
print('Exeception=',e)
|
||||
if sqlor and sqlor.dataChanged:
|
||||
await sqlor.rollback()
|
||||
finally:
|
||||
if sqlor and sqlor.dataChanged:
|
||||
await sqlor.commit()
|
||||
await self.freeSqlor(sqlor)
|
||||
|
||||
async def _aquireConn(self,dbname):
|
||||
"""
|
||||
p = self._cpools.get(dbname)
|
||||
if p == None:
|
||||
p = ConnectionPool(self.databases.get(dbname),self.loop)
|
||||
await p._fillPool()
|
||||
self._cpools[dbname] = p
|
||||
conn = await p.aquire()
|
||||
if self.isAsyncDriver(dbname):
|
||||
cur = await conn.cursor()
|
||||
else:
|
||||
cur = conn.cursor()
|
||||
return self.isAsyncDriver(dbname),conn,cur
|
||||
"""
|
||||
dbdesc = self.databases.get(dbname)
|
||||
driver = myImport(dbdesc['driver'])
|
||||
conn = None
|
||||
cur = None
|
||||
desc = dbdesc['kwargs'].copy()
|
||||
pw = desc.get('password')
|
||||
if pw:
|
||||
desc['password'] = unpassword(pw)
|
||||
if self.isAsyncDriver(dbname):
|
||||
if dbdesc['driver'] == 'sqlite3':
|
||||
conn = await driver.connect(desc['dbname'])
|
||||
else:
|
||||
conn = await driver.connect(**desc)
|
||||
cur = await conn.cursor()
|
||||
return True,conn,cur
|
||||
else:
|
||||
if dbdesc['driver'] == 'sqlite3':
|
||||
conn = driver.connect(desc['dbname'])
|
||||
else:
|
||||
conn = driver.connect(**desc)
|
||||
cur = conn.cursor()
|
||||
return False,conn,cur
|
||||
|
||||
def isAsyncDriver(self,dbname):
|
||||
ret = self.databases[dbname].get('async_mode',False)
|
||||
return ret
|
||||
|
||||
async def _releaseConn(self,dbname,conn,cur):
|
||||
"""
|
||||
if self.isAsyncDriver(dbname):
|
||||
await cur.close()
|
||||
else:
|
||||
try:
|
||||
cur.fetchall()
|
||||
except:
|
||||
pass
|
||||
cur.close()
|
||||
p = self._cpools.get(dbname)
|
||||
if p == None:
|
||||
raise Exception('database (%s) not connected'%dbname)
|
||||
await p.release(conn)
|
||||
"""
|
||||
if self.isAsyncDriver(dbname):
|
||||
try:
|
||||
await cur.close()
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
cur.fetchall()
|
||||
except:
|
||||
pass
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
async def useOrGetSor(self,dbname,**kw):
|
||||
commit = False
|
||||
if kw.get('sor'):
|
||||
sor = kw['sor']
|
||||
else:
|
||||
sor = await self.getSqlor(dbname)
|
||||
commit = True
|
||||
return sor, commit
|
||||
|
||||
def inSqlor(self,func):
|
||||
@wraps(func)
|
||||
async def wrap_func(dbname,NS,*args,**kw):
|
||||
sor, commit = await self.useOrGetSor(dbname, **kw)
|
||||
kw['sor'] = sor
|
||||
try:
|
||||
ret = await func(dbname,NS,*args,**kw)
|
||||
if not commit:
|
||||
return ret
|
||||
try:
|
||||
await sor.conn.commit()
|
||||
except:
|
||||
pass
|
||||
return ret
|
||||
except Exception as e:
|
||||
print('error',sor)
|
||||
if not commit:
|
||||
raise e
|
||||
try:
|
||||
await sor.conn.rollback()
|
||||
except:
|
||||
pass
|
||||
raise e
|
||||
finally:
|
||||
if commit:
|
||||
await self.freeSqlor(sor)
|
||||
|
||||
return wrap_func
|
||||
|
||||
def runSQL(self,func):
|
||||
@wraps(func)
|
||||
async def wrap_func(dbname,NS,*args,**kw):
|
||||
sor, commit = await self.useOrGetSor(dbname,**kw)
|
||||
kw['sor'] = sor
|
||||
ret = None
|
||||
try:
|
||||
desc = await func(dbname,NS,*args,**kw)
|
||||
callback = kw.get('callback',None)
|
||||
kw1 = {}
|
||||
[ kw1.update({k:v}) for k,v in kw.items() if k!='callback' ]
|
||||
ret = await sor.runSQL(desc,NS,callback,**kw1)
|
||||
if commit:
|
||||
try:
|
||||
await sor.conn.commit()
|
||||
except:
|
||||
pass
|
||||
if NS.get('dummy'):
|
||||
return NS['dummy']
|
||||
else:
|
||||
return []
|
||||
except Exception as e:
|
||||
print('error:',e)
|
||||
if not commit:
|
||||
raise e
|
||||
try:
|
||||
await sor.conn.rollback()
|
||||
except:
|
||||
pass
|
||||
raise e
|
||||
finally:
|
||||
if commit:
|
||||
await self.freeSqlor(sor)
|
||||
return wrap_func
|
||||
|
||||
def runSQLPaging(self,func):
|
||||
@wraps(func)
|
||||
async def wrap_func(dbname,NS,*args,**kw):
|
||||
sor, commit = await self.useOrGetSor(dbname,**kw)
|
||||
kw['sor'] = sor
|
||||
try:
|
||||
desc = await func(dbname,NS,*args,**kw)
|
||||
return await sor.runSQLPaging(desc,NS)
|
||||
except Exception as e:
|
||||
print('error',e)
|
||||
raise e
|
||||
finally:
|
||||
if commit:
|
||||
await self.freeSqlor(sor)
|
||||
return wrap_func
|
||||
|
||||
async def runSQLResultFields(self, func):
|
||||
@wraps(func)
|
||||
async def wrap_func(dbname,NS,*args,**kw):
|
||||
sor, commit = await self.useOrGetSor(dbname,**kw)
|
||||
kw['sor'] = sor
|
||||
try:
|
||||
desc = await func(dbname,NS,*args,**kw)
|
||||
ret = await sor.resultFields(desc,NS)
|
||||
return ret
|
||||
except Exception as e:
|
||||
print('error=',e)
|
||||
raise e
|
||||
finally:
|
||||
if commit:
|
||||
await self.freeSqlor(sor)
|
||||
return wrap_func
|
||||
|
||||
def setMeta(self,key,n,v):
|
||||
if not self.meta.get(key):
|
||||
self.meta[key] = {}
|
||||
self.meta[key][n] = v
|
||||
|
||||
def getMeta(self,key,n=None):
|
||||
if not self.meta.get(key):
|
||||
self.meta[key] = {}
|
||||
|
||||
if n is None:
|
||||
return self.meta[key]
|
||||
return self.meta[key].get(n,None)
|
||||
|
||||
async def getTables(self,dbname,**kw):
|
||||
@self.inSqlor
|
||||
async def _getTables(dbname,NS,**kw):
|
||||
sor = kw['sor']
|
||||
ret = await sor.tables()
|
||||
return ret
|
||||
return await _getTables(dbname,{},**kw)
|
||||
|
||||
async def getTableFields(self,dbname,tblname,**kw):
|
||||
@self.inSqlor
|
||||
async def _getTableFields(dbname,NS,tblname,**kw):
|
||||
key = '%s:%s' % (dbname,tblname)
|
||||
fields = self.getMeta(key, 'fields')
|
||||
if fields:
|
||||
return fields
|
||||
sor = kw['sor']
|
||||
ret = await sor.fields(tblname)
|
||||
self.setMeta(key,'fields',ret)
|
||||
return ret
|
||||
return await _getTableFields(dbname,{},tblname,**kw)
|
||||
|
||||
async def getTablePrimaryKey(self,dbname,tblname,**kw):
|
||||
@self.inSqlor
|
||||
async def _getTablePrimaryKey(dbname,NS,tblname,**kw):
|
||||
key = '%s:%s' % (dbname,tblname)
|
||||
pri = self.getMeta(key,'primarykey')
|
||||
if pri:
|
||||
return pri
|
||||
sor = kw['sor']
|
||||
ret = await sor.primary(tblname)
|
||||
self.setMeta(key,'primarykey',ret)
|
||||
return ret
|
||||
return await _getTablePrimaryKey(dbname,{},tblname,**kw)
|
||||
|
||||
async def getTableIndexes(self,dbname,tblname,**kw):
|
||||
@self.inSqlor
|
||||
async def _getTablePrimaryKey(dbname,NS,tblname,**kw):
|
||||
key = '%s:%s' % (dbname,tblname)
|
||||
idxes = self.getMeta(key,'indexes')
|
||||
if idxes:
|
||||
return idxes
|
||||
sor = kw['sor']
|
||||
ret = await sor.indexes(tblname)
|
||||
self.setMeta(key,'indexes',ret)
|
||||
return ret
|
||||
return await _getTablePrimaryKey(dbname,{},tblname,**kw)
|
||||
|
||||
async def getTableForignKeys(self,dbname,tblname,**kw):
|
||||
@self.inSqlor
|
||||
async def _getTableForignKeys(dbname,NS,tblname,**kw):
|
||||
key = '%s:%s' % (dbname,tblname)
|
||||
forignkeys = self.getMeta(key,'forignkeys')
|
||||
if forignkeys:
|
||||
return forignkeys
|
||||
sor = kw['sor']
|
||||
ret = await sor.fkeys(tblname)
|
||||
self.setMeta(key,'forignkeys',forignkeys)
|
||||
return ret
|
||||
return await _getTableForignKeys(dbname,{},tblname,**kw)
|
||||
|
||||
async def runSQL(dbname,sql,ns={},sor=None):
|
||||
pool = DBPools()
|
||||
@pool.runSQL
|
||||
async def desc(dbname,ns,*args,**kw):
|
||||
return {
|
||||
"sql_string":sql
|
||||
}
|
||||
kw = {
|
||||
'sor':sor
|
||||
}
|
||||
x = await desc(dbname,ns,**kw)
|
||||
return x
|
||||
|
||||
async def runSQLPaging(dbname,sql,ns={},sor=None):
|
||||
pool = DBPools()
|
||||
@pool.runSQLPaging
|
||||
async def desc(dbname,ns,*args,**kw):
|
||||
return {
|
||||
"sql_string":sql
|
||||
}
|
||||
kw = {
|
||||
"sor":sor
|
||||
}
|
||||
x = await desc(dbname, ns, **kw)
|
||||
return x
|
||||
|
58
build/lib/sqlor/ddl_template_mysql.py
Normal file
58
build/lib/sqlor/ddl_template_mysql.py
Normal file
@ -0,0 +1,58 @@
|
||||
mysql_ddl_tmpl = """{% macro typeStr(type,len,dec) %}
|
||||
{%- if type=='str' -%}
|
||||
VARCHAR({{len}})
|
||||
{%- elif type=='char' -%}
|
||||
CHAR({{len}})
|
||||
{%- elif type=='long' or type=='int' or type=='short' -%}
|
||||
int
|
||||
{%- elif type=='long' -%}
|
||||
bigint
|
||||
{%- elif type=='float' or type=='double' or type=='ddouble' -%}
|
||||
double({{len}},{{dec}})
|
||||
{%- elif type=='date' -%}
|
||||
date
|
||||
{%- elif type=='time' -%}
|
||||
time
|
||||
{%- elif type=='datetime' -%}
|
||||
datetime
|
||||
{%- elif type=='timestamp' -%}
|
||||
TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
{%- elif type=='text' -%}
|
||||
longtext
|
||||
{%- elif type=='bin' -%}
|
||||
longblob
|
||||
{%- else -%}
|
||||
{{type}}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro defaultValue(defaultv) %}
|
||||
{%- if defaultv %} DEFAULT '{{defaultv}}'{%- endif -%}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro nullStr(nullable) %}
|
||||
{%- if nullable=='no' -%}
|
||||
NOT NULL
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% macro primary() %}
|
||||
,primary key({{','.join(summary[0].primary)}})
|
||||
{% endmacro %}
|
||||
drop table if exists {{summary[0].name}};
|
||||
CREATE TABLE {{summary[0].name}}
|
||||
(
|
||||
{% for field in fields %}
|
||||
`{{field.name}}` {{typeStr(field.type,field.length,field.dec)}} {{nullStr(field.nullable)}} {{defaultValue(field.default)}} {%if field.title -%} comment '{{field.title}}'{%- endif %}{%- if not loop.last -%},{%- endif -%}
|
||||
{% endfor %}
|
||||
{% if summary[0].primary and len(summary[0].primary)>0 %}
|
||||
{{primary()}}
|
||||
{% endif %}
|
||||
)
|
||||
engine=innodb
|
||||
default charset=utf8
|
||||
{% if summary[0].title %}comment '{{summary[0].title}}'{% endif %}
|
||||
;
|
||||
{% for v in indexes %}
|
||||
CREATE {% if v.idxtype=='unique' %}UNIQUE{% endif %} INDEX {{summary[0].name}}_{{v.name}} ON {{summary[0].name}}({{",".join(v.idxfields)}});
|
||||
{%- endfor -%}
|
||||
"""
|
47
build/lib/sqlor/ddl_template_oracle.py
Normal file
47
build/lib/sqlor/ddl_template_oracle.py
Normal file
@ -0,0 +1,47 @@
|
||||
oracle_ddl_tmpl = """{% macro typeStr(type,len,dec) %}
|
||||
{%- if type=='str' -%}
|
||||
VARCHAR2({{len}})
|
||||
{%- elif type=='char' -%}
|
||||
CHAR({{len}})
|
||||
{%- elif type=='long' or type=='int' or type=='short' -%}
|
||||
NUMBER
|
||||
{%- elif type=='float' or type=='double' or type=='ddouble' -%}
|
||||
NUMBER({{len}},{{dec}})
|
||||
{%- elif type=='date' or type=='time' -%}
|
||||
DATE
|
||||
{%- elif type=='timestamp' -%}
|
||||
TIMESTAMP
|
||||
{%- elif type=='text' -%}
|
||||
CLOB
|
||||
{%- elif type=='bin' -%}
|
||||
BLOB
|
||||
{%- else -%}
|
||||
{{type}}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
{% macro nullStr(nullable) %}
|
||||
{%- if nullable=='no' -%}
|
||||
NOT NULL
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% macro primary() %}
|
||||
,primary key({{','.join(summary[0].primary)}})
|
||||
{% endmacro %}
|
||||
drop table {{summary[0].name}};
|
||||
CREATE TABLE {{summary[0].name}}
|
||||
(
|
||||
{% for field in fields %}
|
||||
{{field.name}} {{typeStr(field.type,field.length,field.dec)}} {{nullStr(field.nullable)}}{%- if not loop.last -%},{%- endif -%}
|
||||
{% endfor %}
|
||||
{% if summary[0].primary and len(summary[0].primary)>0 %}
|
||||
{{primary()}}
|
||||
{% endif %}
|
||||
);
|
||||
{% for v in indexes %}
|
||||
CREATE {% if v.idxtype=='unique' %}UNIQUE{% endif %} INDEX {{summary[0].name}}_{{v.name}} ON {{summary[0].name}}({{",".join(v.idxfields)}});
|
||||
{%- endfor -%}
|
||||
COMMENT ON TABLE {{summary[0].name}} IS '{{summary[0].title}}';
|
||||
{% for field in fields %}
|
||||
COMMENT ON COLUMN {{summary[0].name}}.{{field.name}} is '{{field.title}}';
|
||||
{% endfor %}
|
||||
"""
|
45
build/lib/sqlor/ddl_template_postgresql.py
Normal file
45
build/lib/sqlor/ddl_template_postgresql.py
Normal file
@ -0,0 +1,45 @@
|
||||
postgresql_ddl_tmpl = """{% macro typeStr(type,len,dec) %}
|
||||
{%- if type=='str' -%}
|
||||
VARCHAR({{len}})
|
||||
{%- elif type=='char' -%}
|
||||
CHAR({{len}})
|
||||
{%- elif type=='long' or type=='int' or type=='short' -%}
|
||||
NUMERIC(30,0)
|
||||
{%- elif type=='float' or type=='double' or type=='ddouble' -%}
|
||||
NUMERIC({{len}},{{dec}})
|
||||
{%- elif type=='date' -%}
|
||||
DATE
|
||||
{%- elif type=='time' -%}
|
||||
TIME
|
||||
{%- elif type=='timestamp' -%}
|
||||
TIMESTAMP
|
||||
{%- else -%}
|
||||
{{type}}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
{% macro nullStr(nullable) %}
|
||||
{%- if nullable=='no' -%}
|
||||
NOT NULL
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% macro primary() %}
|
||||
,PRIMARY KEY({{','.join(summary[0].primary)}})
|
||||
{% endmacro %}
|
||||
DROP TABLE IF EXISTS {{summary[0].name}};
|
||||
CREATE TABLE {{summary[0].name}}
|
||||
(
|
||||
{% for field in fields %}
|
||||
{{field.name}} {{typeStr(field.type,field.length,field.dec)}} {{nullStr(field.nullable)}}{%- if not loop.last -%},{%- endif -%}
|
||||
{% endfor %}
|
||||
{% if summary[0].primary and len(summary[0].primary)>0 %}
|
||||
{{primary()}}
|
||||
{% endif %}
|
||||
);
|
||||
{% for v in indexes %}
|
||||
CREATE {% if v.idxtype=='unique' %}UNIQUE{% endif %} INDEX {{summary[0].name}}_{{v.name}} ON {{summary[0].name}}({{",".join(v.idxfields)}});
|
||||
{%- endfor -%}
|
||||
COMMENT ON TABLE {{summary[0].name}} IS '{{summary[0].title}}';
|
||||
{% for field in fields %}
|
||||
COMMENT ON COLUMN {{summary[0].name}}.{{field.name}} is '{{field.title}}';
|
||||
{% endfor %}
|
||||
"""
|
37
build/lib/sqlor/ddl_template_sqlite3.py
Normal file
37
build/lib/sqlor/ddl_template_sqlite3.py
Normal file
@ -0,0 +1,37 @@
|
||||
sqlite3_ddl_tmpl = """{% macro typeStr(type,len,dec) %}
|
||||
{%- if type in ['str', 'char', 'date', 'time', 'datetime', 'timestamp'] -%}
|
||||
TEXT
|
||||
{%- elif type in ['long', 'int', 'short', 'longlong' ] -%}
|
||||
int
|
||||
{%- elif type in ['float', 'double', 'ddouble'] -%}
|
||||
real
|
||||
{%- elif type=='bin' -%}
|
||||
blob
|
||||
{%- else -%}
|
||||
{{type}}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
{% macro nullStr(nullable) %}
|
||||
{%- if nullable=='no' -%}
|
||||
NOT NULL
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% macro primary() %}
|
||||
,primary key({{','.join(summary[0].primary)}})
|
||||
{% endmacro %}
|
||||
drop table if exists {{summary[0].name}};
|
||||
CREATE TABLE {{summary[0].name}}
|
||||
(
|
||||
{% for field in fields %}
|
||||
`{{field.name}}` {{typeStr(field.type,field.length,field.dec)}} {{nullStr(field.nullable)}}{%- if not loop.last -%},{%- endif -%} {%if field.title -%} -- {{field.title}}{%- endif %}
|
||||
{% endfor %}
|
||||
{% if summary[0].primary and len(summary[0].primary)>0 %}
|
||||
{{primary()}}
|
||||
{% endif %}
|
||||
)
|
||||
{% if summary[0].title %} --{{summary[0].title}}{% endif %}
|
||||
;
|
||||
{% for v in indexes %}
|
||||
CREATE {% if v.idxtype=='unique' %}UNIQUE{% endif %} INDEX {{summary[0].name}}_{{v.name}} ON {{summary[0].name}}({{",".join(v.idxfields)}});
|
||||
{%- endfor -%}
|
||||
"""
|
49
build/lib/sqlor/ddl_template_sqlserver.py
Normal file
49
build/lib/sqlor/ddl_template_sqlserver.py
Normal file
@ -0,0 +1,49 @@
|
||||
sqlserver_ddl_tmpl = """{% macro typeStr(type,len,dec) %}
|
||||
{%- if type=='str' -%}
|
||||
NVARCHAR({{len}})
|
||||
{%- elif type=='char' -%}
|
||||
CHAR({{len}})
|
||||
{%- elif type=='long' or type=='int' or type=='short' -%}
|
||||
NUMERIC
|
||||
{%- elif type=='float' or type=='double' or type=='ddouble' -%}
|
||||
numeric({{len}},{{dec}})
|
||||
{%- elif type=='date' or type=='time' -%}
|
||||
DATE
|
||||
{%- elif type=='timestamp' -%}
|
||||
TIMESTAMP
|
||||
{%- elif type=='text' -%}
|
||||
NVARCHAR(MAX)
|
||||
{%- elif type=='bin' -%}
|
||||
IMAGE
|
||||
{%- else -%}
|
||||
{{type}}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
{% macro nullStr(nullable) %}
|
||||
{%- if nullable=='no' -%}
|
||||
NOT NULL
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro primary() %}
|
||||
,primary key({{','.join(summary[0].primary)}})
|
||||
{% endmacro %}
|
||||
|
||||
drop table dbo.{{summary[0].name}};
|
||||
CREATE TABLE dbo.{{summary[0].name}}
|
||||
(
|
||||
{% for field in fields %}
|
||||
{{field.name}} {{typeStr(field.type,field.length,field.dec)}} {{nullStr(field.nullable)}}{%- if not loop.last -%},{%- endif -%}
|
||||
{% endfor %}
|
||||
{% if summary[0].primary and len(summary[0].primary)>0 %}
|
||||
{{primary()}}
|
||||
{% endif %}
|
||||
)
|
||||
{% for v in indexes %}
|
||||
CREATE {% if v.idxtype=='unique' %}UNIQUE{% endif %} INDEX {{summary[0].name}}_{{v.name}} ON {{summary[0].name}}({{",".join(v.idxfields)}});
|
||||
{%- endfor -%}
|
||||
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'{{summary[0].title}}' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'{{summary[0].name}}'
|
||||
{% for field in fields %}
|
||||
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'{{field.title}}' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'{{summary[0].name}}', @level2type=N'COLUMN',@level2name=N'{{field.name}}'
|
||||
{% endfor %}
|
||||
"""
|
180
build/lib/sqlor/filter.py
Normal file
180
build/lib/sqlor/filter.py
Normal file
@ -0,0 +1,180 @@
|
||||
# -*- coding:utf8 -*-
|
||||
"""
|
||||
过滤器解释器
|
||||
解释json格式的SQL查询过滤
|
||||
过滤支持:
|
||||
双目关系运算符:
|
||||
AND
|
||||
OR
|
||||
单目关系运算符:
|
||||
NOT
|
||||
表达式:
|
||||
表达关系有:=,<>,>,<,>=,<=,in,not in
|
||||
a=b格式的
|
||||
{
|
||||
"and":[
|
||||
{
|
||||
"field":'field1'
|
||||
"op":"=",
|
||||
"const":1
|
||||
"var":"var1"
|
||||
},
|
||||
{
|
||||
"or":[...]
|
||||
}
|
||||
{
|
||||
"not":{...}
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
try:
|
||||
import ujson as json
|
||||
except:
|
||||
import json
|
||||
|
||||
class DBFilter(object):
|
||||
operators = [
|
||||
"=",
|
||||
"!=",
|
||||
"IN",
|
||||
"NOT IN",
|
||||
">",
|
||||
">=",
|
||||
"<",
|
||||
"<=",
|
||||
"IS NULL",
|
||||
"IS NOT NULL",
|
||||
"LIKE",
|
||||
"NOT LIKE"
|
||||
]
|
||||
logic = [
|
||||
"AND",
|
||||
"OR",
|
||||
"NOT"
|
||||
]
|
||||
def __init__(self,filterjson):
|
||||
if isinstance(filterjson, str):
|
||||
filterjson = json.loads(filterjson)
|
||||
self.filterjson = filterjson
|
||||
|
||||
def gen(self, ns={}):
|
||||
self.consts = {}
|
||||
ret = self._genFilterSQL(self.filterjson, ns)
|
||||
ns.update(self.consts)
|
||||
return ret
|
||||
|
||||
def get_variables(self):
|
||||
return self.get_filters_variables(self.filterjson)
|
||||
|
||||
def get_filters_variables(self, filters):
|
||||
vs = {}
|
||||
keys = [ k for k in filters.keys() ]
|
||||
if len(keys) == 1:
|
||||
fs = filters[keys[0]]
|
||||
if isinstance(fs, list):
|
||||
for f in fs:
|
||||
v = self.get_filters_variables(f)
|
||||
if v:
|
||||
vs.update(v)
|
||||
return vs
|
||||
else:
|
||||
v = self.get_filters_variables(fs)
|
||||
if v:
|
||||
vs.update(v)
|
||||
return vs
|
||||
if 'var' in keys:
|
||||
return {
|
||||
filters['var']:filters['field']
|
||||
}
|
||||
return None
|
||||
|
||||
def _genFilterSQL(self,fj, ns):
|
||||
keys = [ i for i in fj.keys()]
|
||||
if len(keys) == 1:
|
||||
key = keys[0]
|
||||
if key.lower() in ['and','or']:
|
||||
if type(fj[key]) != type([]) or len(fj[key])<2:
|
||||
raise Exception(key + ':' + json.dumps(fj[key]) + ':is not a array, or array length < 2')
|
||||
subsqls = [self._genFilterSQL(f, ns) for f in fj[key]]
|
||||
subsqls = [ s for s in subsqls if s is not None]
|
||||
if len(subsqls) < 1:
|
||||
return None
|
||||
if len(subsqls) < 2:
|
||||
return subsqls[0]
|
||||
|
||||
a = ' %s ' % key
|
||||
sql = a.join(subsqls)
|
||||
if key == 'or':
|
||||
return ' (%s) ' % sql
|
||||
return sql
|
||||
if key.lower() == 'not':
|
||||
if type(fj[key]) != type({}):
|
||||
raise Exception(key + ':' + json.dumps(fj[key]) + ':is not a dict')
|
||||
a = ' %s ' % key
|
||||
sql = self._genFilterSQL(fj[key], ns)
|
||||
if not sql:
|
||||
return None
|
||||
return ' not (%s) ' % sql
|
||||
return self._genFilterItems(fj, ns)
|
||||
|
||||
def _genFilterItems(self,fj, ns):
|
||||
keys = fj.keys()
|
||||
assert 'field' in keys
|
||||
assert 'op' in keys
|
||||
assert 'const' in keys or 'var' in keys or fj['op'].upper() in ['IS NULL', 'IS NOT NULL']
|
||||
op = fj.get('op').upper()
|
||||
assert op in self.operators
|
||||
|
||||
if op in ['IS NULL', 'IS NOT NULL']:
|
||||
return f"{fj['field']} {op}"
|
||||
|
||||
var = fj.get('var')
|
||||
if var and not var in ns.keys():
|
||||
return None
|
||||
|
||||
if 'const' in keys:
|
||||
cnt = len(self.consts.keys())
|
||||
name = f'filter_const_{cnt}'
|
||||
self.consts.update({name:fj.get('const')})
|
||||
sql = '%s %s ${%s}$' % (fj.get('field'), fj.get('op'), name)
|
||||
return sql
|
||||
|
||||
sql = '%s %s ${%s}$' % (fj.get('field'), fj.get('op'), fj.get('var'))
|
||||
return sql
|
||||
|
||||
def default_filterjson(fields: list, ns: dict):
|
||||
fj = {}
|
||||
c = [ {
|
||||
'field':k,
|
||||
'op':'=',
|
||||
'var':k
|
||||
} for k in ns.keys() if k in fields ]
|
||||
print(f'default_filterjson():{c=}')
|
||||
if len(c) < 1:
|
||||
return None
|
||||
if len(c) < 2:
|
||||
return c[0]
|
||||
return {
|
||||
'AND':c
|
||||
}
|
||||
|
||||
if __name__ == '__main__':
|
||||
fj = {
|
||||
"AND":[
|
||||
{
|
||||
"field":'field1',
|
||||
"op":"=",
|
||||
"var":"name"
|
||||
},
|
||||
{
|
||||
"field":'del_flg',
|
||||
"op":"=",
|
||||
"const":"0"
|
||||
}]
|
||||
}
|
||||
|
||||
dbf = DBFilter(fj)
|
||||
print(fj)
|
||||
print(dbf.gen({'name':'joe'}))
|
||||
print(f'{dbf.consts=}')
|
174
build/lib/sqlor/mssqlor.py
Normal file
174
build/lib/sqlor/mssqlor.py
Normal file
@ -0,0 +1,174 @@
|
||||
# -*- coding:utf8 -*-
|
||||
from .sor import SQLor
|
||||
from .ddl_template_sqlserver import sqlserver_ddl_tmpl
|
||||
|
||||
class MsSqlor(SQLor):
|
||||
ddl_template = sqlserver_ddl_tmpl
|
||||
db2modelTypeMapping = {
|
||||
'bit':'short',
|
||||
'tinyint':'short',
|
||||
'date':'date',
|
||||
'bigint':'long',
|
||||
'smallint':'short',
|
||||
'int':'long',
|
||||
'decimal':'float',
|
||||
'numeric':'float',
|
||||
'smallmoney':'float',
|
||||
'money':'float',
|
||||
'real':'float',
|
||||
'float':'float',
|
||||
'datetime':'date',
|
||||
'timestamp':'timestamp',
|
||||
'uniqueidentifier':'timestamp',
|
||||
'char':'char',
|
||||
'varchar':'str',
|
||||
'text':'text',
|
||||
'nchar':'str',
|
||||
'nvarchar':'str',
|
||||
'ntext':'text',
|
||||
'binary':'str',
|
||||
'varbinary':'str',
|
||||
'image':'file',
|
||||
}
|
||||
model2dbTypemapping = {
|
||||
'date':'datetime',
|
||||
'time':'date',
|
||||
'timestamp':'timestamp',
|
||||
'str':'nvarchar',
|
||||
'char':'char',
|
||||
'short':'int',
|
||||
'long':'numeric',
|
||||
'float':'numeric',
|
||||
'text':'ntext',
|
||||
'file':'image',
|
||||
}
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='pymssql'
|
||||
|
||||
def grammar(self):
|
||||
return {
|
||||
'select':select_stmt,
|
||||
}
|
||||
|
||||
def placeHolder(self,varname,pos=None):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return '%s'
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
if type(dataList) == type({}):
|
||||
d = [ i for i in dataList.values()]
|
||||
else:
|
||||
d = [ i['value'] for i in dataList]
|
||||
return tuple(d)
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
return u"""select *
|
||||
from (
|
||||
select row_number() over(order by $[sort]$) as _row_id,page_s.*
|
||||
from (%s) page_s
|
||||
) A
|
||||
where _row_id >= $[from_line]$ and _row_id < $[end_line]$"""
|
||||
|
||||
def tablesSQL(self):
|
||||
sqlcmd = u"""select
|
||||
lower(d.name) as name,
|
||||
lower(cast(Isnull(f.VALUE,d.name) as nvarchar )) title
|
||||
from sysobjects d
|
||||
left join sys.extended_properties f on d.id = f.major_id and f.minor_id = 0
|
||||
where d.xtype = 'U'"""
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self,tablename=None):
|
||||
sqlcmd=u"""SELECT name = lower(a.name)
|
||||
,type = b.name
|
||||
,length = Columnproperty(a.id,a.name,'PRECISION')
|
||||
,dec = Isnull(Columnproperty(a.id,a.name,'Scale'),null)
|
||||
,nullable = CASE
|
||||
WHEN a.isnullable = 1 THEN 'yes'
|
||||
ELSE 'no'
|
||||
END
|
||||
,title = lower(cast(Isnull(g.[value],a.name) as nvarchar) )
|
||||
,table_name = lower(d.name)
|
||||
FROM syscolumns a
|
||||
LEFT JOIN systypes b
|
||||
ON a.xusertype = b.xusertype
|
||||
INNER JOIN sysobjects d
|
||||
ON (a.id = d.id)
|
||||
AND (d.xtype = 'U')
|
||||
AND (d.name <> 'dtproperties')
|
||||
INNER JOIN sys.all_objects c
|
||||
ON d.id=c.object_id
|
||||
AND schema_name(schema_id)='dbo'
|
||||
LEFT JOIN sys.extended_properties g
|
||||
ON (a.id = g.major_id)
|
||||
AND (a.colid = g.minor_id)
|
||||
LEFT JOIN sys.extended_properties f
|
||||
ON (d.id = f.major_id)
|
||||
AND (f.minor_id = 0)"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ where lower(d.name)='%s'
|
||||
ORDER BY a.id,a.colorder""" % tablename.lower()
|
||||
else:
|
||||
sqlcmd = sqlcmd + """ ORDER BY a.id,a.colorder"""
|
||||
return sqlcmd
|
||||
|
||||
def fkSQL(self,tablename=None):
|
||||
sqlcmd = u"""select
|
||||
MainCol.name AS field -- [主表列名]
|
||||
,oSub.name AS fk_table -- [子表名称],
|
||||
,SubCol.name AS fk_field -- [子表列名],
|
||||
from
|
||||
sys.foreign_keys fk
|
||||
JOIN sys.all_objects oSub
|
||||
ON (fk.parent_object_id = oSub.object_id)
|
||||
JOIN sys.all_objects oMain
|
||||
ON (fk.referenced_object_id = oMain.object_id)
|
||||
JOIN sys.foreign_key_columns fkCols
|
||||
ON (fk.object_id = fkCols.constraint_object_id)
|
||||
JOIN sys.columns SubCol
|
||||
ON (oSub.object_id = SubCol.object_id
|
||||
AND fkCols.parent_column_id = SubCol.column_id)
|
||||
JOIN sys.columns MainCol
|
||||
ON (oMain.object_id = MainCol.object_id
|
||||
AND fkCols.referenced_column_id = MainCol.column_id)"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ where lower(oMain.name) = '%s'""" % tablename.lower()
|
||||
|
||||
return sqlcmd
|
||||
|
||||
def pkSQL(self,tablename=None):
|
||||
sqlcmd = u"""select
|
||||
lower(a.table_name) as table_name,
|
||||
lower(b.column_name) as field_name
|
||||
from information_schema.table_constraints a
|
||||
inner join information_schema.constraint_column_usage b
|
||||
on a.constraint_name = b.constraint_name
|
||||
where a.constraint_type = 'PRIMARY KEY'"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ and lower(a.table_name) = '%s'""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def indexesSQL(self,tablename=None):
|
||||
sqlcmd = """SELECT
|
||||
index_name=lower(IDX.Name),
|
||||
index_type=IDX.is_unique,
|
||||
column_name=lower(C.Name)
|
||||
FROM sys.indexes IDX
|
||||
INNER JOIN sys.index_columns IDXC
|
||||
ON IDX.[object_id]=IDXC.[object_id]
|
||||
AND IDX.index_id=IDXC.index_id
|
||||
LEFT JOIN sys.key_constraints KC
|
||||
ON IDX.[object_id]=KC.[parent_object_id]
|
||||
AND IDX.index_id=KC.unique_index_id
|
||||
INNER JOIN sys.objects O
|
||||
ON O.[object_id]=IDX.[object_id]
|
||||
INNER JOIN sys.columns C
|
||||
ON O.[object_id]=C.[object_id]
|
||||
AND O.type='U'
|
||||
AND O.is_ms_shipped=0
|
||||
AND IDXC.Column_id=C.Column_id"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ where lower(O.name)='%s'""" % tablename.lower()
|
||||
return sqlcmd
|
143
build/lib/sqlor/mysqlor.py
Normal file
143
build/lib/sqlor/mysqlor.py
Normal file
@ -0,0 +1,143 @@
|
||||
# -*- coding:utf8 -*-
|
||||
from appPublic.argsConvert import ArgsConvert,ConditionConvert
|
||||
|
||||
from .sor import SQLor
|
||||
from .const import ROWS
|
||||
from .ddl_template_mysql import mysql_ddl_tmpl
|
||||
class MySqlor(SQLor):
|
||||
ddl_template = mysql_ddl_tmpl
|
||||
db2modelTypeMapping = {
|
||||
'tinyint':'short',
|
||||
'smallint':'short',
|
||||
'mediumint':'long',
|
||||
'int':'long',
|
||||
'bigint':'long',
|
||||
'decimal':'float',
|
||||
'double':'float',
|
||||
'float':'float',
|
||||
'char':'char',
|
||||
'varchar':'str',
|
||||
'tinyblob':'text',
|
||||
'tinytext':'text',
|
||||
'mediumblob':'text',
|
||||
'mediumtext':'text',
|
||||
'blob':'text',
|
||||
'text':'text',
|
||||
'mediumblob':'text',
|
||||
'mediumtext':'text',
|
||||
'longblob':'bin',
|
||||
'longtext':'text',
|
||||
'barbinary':'text',
|
||||
'binary':'text',
|
||||
'date':'date',
|
||||
'time':'time',
|
||||
'datetime':'datetime',
|
||||
'timestamp':'datestamp',
|
||||
'year':'short',
|
||||
}
|
||||
model2dbTypemapping = {
|
||||
'date':'date',
|
||||
'time':'date',
|
||||
'timestamp':'timestamp',
|
||||
'str':'varchar',
|
||||
'char':'char',
|
||||
'short':'int',
|
||||
'long':'bigint',
|
||||
'float':'double',
|
||||
'text':'longtext',
|
||||
'bin':'longblob',
|
||||
'file':'longblob',
|
||||
}
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
if name=='pymysql':
|
||||
return True
|
||||
return False
|
||||
|
||||
def grammar(self):
|
||||
return {
|
||||
'select':select_stmt,
|
||||
}
|
||||
|
||||
def placeHolder(self,varname,pos=None):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return '%s'
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
if type(dataList) == type({}):
|
||||
d = [ i for i in dataList.values()]
|
||||
else:
|
||||
d = [ i['value'] for i in dataList]
|
||||
return tuple(d)
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
return """select *, row_number() over(order by $[sort]$) as row_num_ from (%s) A limit $[from_line]$, $[rows]$"""
|
||||
return """select * from (%s) A order by $[sort]$
|
||||
limit $[from_line]$,$[rows]$"""
|
||||
|
||||
def tablesSQL(self):
|
||||
sqlcmd = """SELECT lower(TABLE_NAME) as name, lower(TABLE_COMMENT) as title FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '%s'""" % self.dbdesc.get('dbname','unknown')
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self,tablename=None):
|
||||
sqlcmd="""
|
||||
select
|
||||
lower(column_name) as name,
|
||||
data_type as type,
|
||||
case when character_maximum_length is null then NUMERIC_PRECISION
|
||||
else character_maximum_length end
|
||||
as length,
|
||||
NUMERIC_SCALE as 'dec',
|
||||
lower(is_nullable) as nullable,
|
||||
column_comment as title,
|
||||
lower(table_name) as table_name
|
||||
from information_schema.columns where lower(TABLE_SCHEMA) = '%s' """ % self.dbdesc.get('dbname','unknown').lower()
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """and lower(table_name)='%s';""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def fkSQL(self,tablename=None):
|
||||
sqlcmd = """SELECT C.TABLE_SCHEMA 拥有者,
|
||||
C.REFERENCED_TABLE_NAME 父表名称 ,
|
||||
C.REFERENCED_COLUMN_NAME 父表字段 ,
|
||||
C.TABLE_NAME 子表名称,
|
||||
C.COLUMN_NAME 子表字段,
|
||||
C.CONSTRAINT_NAME 约束名,
|
||||
T.TABLE_COMMENT 表注释,
|
||||
R.UPDATE_RULE 约束更新规则,
|
||||
R.DELETE_RULE 约束删除规则
|
||||
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE C
|
||||
JOIN INFORMATION_SCHEMA. TABLES T
|
||||
ON T.TABLE_NAME = C.TABLE_NAME
|
||||
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R
|
||||
ON R.TABLE_NAME = C.TABLE_NAME
|
||||
AND R.CONSTRAINT_NAME = C.CONSTRAINT_NAME
|
||||
AND R.REFERENCED_TABLE_NAME = C.REFERENCED_TABLE_NAME
|
||||
WHERE C.REFERENCED_TABLE_NAME IS NOT NULL ;
|
||||
and C.TABLE_SCHEMA = '%s'
|
||||
""" % self.dbdesc.get('dbname','unknown').lower()
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + " and C.REFERENCED_TABLE_NAME = '%s'" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def pkSQL(self,tablename=None):
|
||||
sqlcmd = """SELECT distinct column_name as name FROM INFORMATION_SCHEMA.`KEY_COLUMN_USAGE` WHERE table_name='%s' AND constraint_name='PRIMARY'
|
||||
""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def indexesSQL(self,tablename=None):
|
||||
sqlcmd = """SELECT DISTINCT
|
||||
lower(index_name) as index_name,
|
||||
case NON_UNIQUE
|
||||
when 1 then 'unique'
|
||||
else ''
|
||||
end as is_unique,
|
||||
lower(column_name) as column_name
|
||||
FROM
|
||||
information_schema.statistics
|
||||
WHERE
|
||||
table_schema = '%s'""" % self.dbdesc.get('dbname','unknown')
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ AND table_name = '%s'""" % tablename.lower()
|
||||
return sqlcmd
|
130
build/lib/sqlor/oracleor.py
Normal file
130
build/lib/sqlor/oracleor.py
Normal file
@ -0,0 +1,130 @@
|
||||
from .sor import SQLor
|
||||
from .ddl_template_oracle import oracle_ddl_tmpl
|
||||
class Oracleor(SQLor):
|
||||
ddl_template = oracle_ddl_tmpl
|
||||
db2modelTypeMapping = {
|
||||
'char':'char',
|
||||
'nchar':'str',
|
||||
'varchar':'str',
|
||||
'varchar2':'str',
|
||||
'nvarchar2':'str',
|
||||
'number':'long',
|
||||
'integer':'long',
|
||||
'binary_float':'float',
|
||||
'binary_double':'float',
|
||||
'float':'float',
|
||||
'timestamp':'timestamp',
|
||||
'timestamp with time zone':'timestamp',
|
||||
'timestamp with local time zone':'timestamp',
|
||||
'interval year to moth':'date',
|
||||
'interval day to second':'timestamp',
|
||||
'clob':'text',
|
||||
'nclob':'text',
|
||||
'blob':'file',
|
||||
'bfile':'file',
|
||||
'date':'date',
|
||||
}
|
||||
model2dbTypemapping = {
|
||||
'date':'date',
|
||||
'time':'date',
|
||||
'timestamp':'date',
|
||||
'str':'varchar2',
|
||||
'char':'char',
|
||||
'short':'number',
|
||||
'long':'number',
|
||||
'float':'number',
|
||||
'text':'nclob',
|
||||
'file':'blob',
|
||||
}
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='cx_Oracle'
|
||||
|
||||
def grammar(self):
|
||||
return {
|
||||
'select':select_stmt,
|
||||
}
|
||||
|
||||
def placeHolder(self,varname,pos=None):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return ':%s' % varname
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
if type(dataList) == type({}):
|
||||
return dataList
|
||||
d = {}
|
||||
[ d.update({i['name']:i['value']}) for i in dataList ]
|
||||
return d
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
return u"""select *
|
||||
from (
|
||||
select page_s.*,rownum row_id
|
||||
from (%s) page_s
|
||||
order by $[sort]$
|
||||
)
|
||||
where row_id >=$[from_line]$ and row_id < $[end_line]$"""
|
||||
|
||||
def tablesSQL(self):
|
||||
sqlcmd = """select
|
||||
lower(table_name) as name,
|
||||
lower(decode(comments,null,table_name,comments)) as title
|
||||
from USER_TAB_COMMENTS where table_type = 'TABLE'"""
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self,tablename=None):
|
||||
sqlcmd="""select lower(utc.COLUMN_NAME) name
|
||||
,utc.DATA_TYPE type
|
||||
,utc.DATA_LENGTH length
|
||||
,utc.data_scale dec
|
||||
,case when utc.nullable = 'Y' then 'yes' else 'no' end nullable
|
||||
,lower(nvl(ucc.comments,utc.COLUMN_NAME)) title
|
||||
,lower(utc.table_name) as table_name
|
||||
from user_tab_cols utc left join USER_COL_COMMENTS ucc on utc.table_name = ucc.table_name and utc.COLUMN_NAME = ucc.COLUMN_NAME"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ where lower(utc.table_name) = '%s'""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def fkSQL(self,tablename=None):
|
||||
tablename = tablename.lower()
|
||||
sqlcmd = """select
|
||||
distinct(ucc.column_name) as field,rela.table_name as fk_table,rela.column_name as fk_field
|
||||
from
|
||||
user_constraints uc,user_cons_columns ucc,
|
||||
(
|
||||
select t2.table_name,t2.column_name,t1.r_constraint_name
|
||||
from user_constraints t1,user_cons_columns t2
|
||||
where t1.r_constraint_name=t2.constraint_name
|
||||
) rela
|
||||
where
|
||||
uc.constraint_name=ucc.constraint_name
|
||||
and uc.r_constraint_name=rela.r_constraint_name"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ and lower(uc.table_name)='%s'""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def pkSQL(self,tablename=None):
|
||||
sqlcmd = """
|
||||
select
|
||||
lower(col.table_name) table_name,
|
||||
lower(col.column_name) as field_name
|
||||
from
|
||||
user_constraints con,user_cons_columns col
|
||||
where
|
||||
con.constraint_name=col.constraint_name and con.constraint_type='P'"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ and lower(col.table_name)='%s'""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def indexesSQL(self,tablename=None):
|
||||
sqlcmd = """select
|
||||
lower(a.index_name) index_name,
|
||||
lower(a.UNIQUENESS) is_unique,
|
||||
lower(b.column_name) column_name
|
||||
from user_indexes a, user_ind_columns b
|
||||
where a.index_name = b.index_name"""
|
||||
if tablename is not None:
|
||||
sqlcmd += """ and lower(a.table_name) = lower('%s')""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
171
build/lib/sqlor/postgresqlor.py
Normal file
171
build/lib/sqlor/postgresqlor.py
Normal file
@ -0,0 +1,171 @@
|
||||
from .sor import SQLor
|
||||
from .ddl_template_postgresql import postgresql_ddl_tmpl
|
||||
|
||||
class PostgreSQLor(SQLor):
|
||||
ddl_template = postgresql_ddl_tmpl
|
||||
db2modelTypeMapping = {
|
||||
'smallint':'short',
|
||||
'integer':'long',
|
||||
'bigint':'llong',
|
||||
'decimal':'float',
|
||||
'numeric':'float',
|
||||
'real':'float',
|
||||
'double':'float',
|
||||
'serial':'long',
|
||||
'bigserial':'llong',
|
||||
'char':'char',
|
||||
'character':'char',
|
||||
'varchar':'str',
|
||||
'character varying':'str',
|
||||
'text':'text',
|
||||
'timestamp':'timestamp',
|
||||
'date':'date',
|
||||
'time':'time',
|
||||
'boolean':'char',
|
||||
'bytea':'file'
|
||||
}
|
||||
model2dbTypemapping = {
|
||||
'date':'date',
|
||||
'time':'date',
|
||||
'timestamp':'timestamp',
|
||||
'str':'varchar',
|
||||
'char':'char',
|
||||
'short':'smallint',
|
||||
'long':'integer',
|
||||
'float':'numeric',
|
||||
'text':'text',
|
||||
'file':'bytea',
|
||||
}
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='psycopg2' or name=='pyguass'
|
||||
|
||||
def grammar(self):
|
||||
return {
|
||||
'select':select_stmt,
|
||||
}
|
||||
|
||||
def placeHolder(self,varname,i):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return '%%(%s)s' % varname
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
if type(dataList) == type({}):
|
||||
return dataList
|
||||
d = { i['name']:i['value'] for i in dataList }
|
||||
return d
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
return u"""select *
|
||||
from (
|
||||
select page_s.*,rownum row_id
|
||||
from (%s) page_s
|
||||
order by $[sort]$
|
||||
)
|
||||
where row_id >=$[from_line]$ and row_id < $[end_line]$"""
|
||||
|
||||
def tablesSQL(self):
|
||||
sqlcmd = """select x.name, y.description as title
|
||||
from
|
||||
(select a.name,c.oid
|
||||
from
|
||||
(select lower(tablename) as name from pg_tables where schemaname='public') a,
|
||||
pg_class c
|
||||
where a.name = c.relname) x
|
||||
left join pg_description y
|
||||
on x.oid=y.objoid
|
||||
and y.objsubid='0'"""
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self,tablename=None):
|
||||
sqlcmd="""SELECT
|
||||
a.attname AS name,
|
||||
t.typname AS type,
|
||||
case t.typname
|
||||
when 'varchar' then a.atttypmod - 4
|
||||
when 'numeric' then (a.atttypmod - 4) / 65536
|
||||
else null
|
||||
end as length,
|
||||
case t.typname
|
||||
when 'numeric' then (a.atttypmod - 4) %% 65536
|
||||
else null
|
||||
end as dec,
|
||||
case a.attnotnull
|
||||
when 't' then 'no'
|
||||
when 'f' then 'yes'
|
||||
end as nullable,
|
||||
b.description AS title
|
||||
FROM pg_class c, pg_attribute a
|
||||
LEFT JOIN pg_description b
|
||||
ON a.attrelid = b.objoid
|
||||
AND a.attnum = b.objsubid, pg_type t
|
||||
WHERE lower(c.relname) = '%s'
|
||||
AND a.attnum > 0
|
||||
AND a.attrelid = c.oid
|
||||
AND a.atttypid = t.oid
|
||||
ORDER BY a.attnum;
|
||||
""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def fkSQL(self,tablename=None):
|
||||
tablename = tablename.lower()
|
||||
sqlcmd = """select
|
||||
distinct(ucc.column_name) as field,rela.table_name as fk_table,rela.column_name as fk_field
|
||||
from
|
||||
user_constraints uc,user_cons_columns ucc,
|
||||
(
|
||||
select t2.table_name,t2.column_name,t1.r_constraint_name
|
||||
from user_constraints t1,user_cons_columns t2
|
||||
where t1.r_constraint_name=t2.constraint_name
|
||||
) rela
|
||||
where
|
||||
uc.constraint_name=ucc.constraint_name
|
||||
and uc.r_constraint_name=rela.r_constraint_name"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ and lower(uc.table_name)='%s'""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def pkSQL(self,tablename=None):
|
||||
sqlcmd="""
|
||||
select
|
||||
pg_attribute.attname as field_name,
|
||||
lower(pg_class.relname) as table_name
|
||||
from pg_constraint
|
||||
inner join pg_class
|
||||
on pg_constraint.conrelid = pg_class.oid
|
||||
inner join pg_attribute
|
||||
on pg_attribute.attrelid = pg_class.oid
|
||||
and pg_attribute.attnum = pg_constraint.conkey[1]
|
||||
inner join pg_type
|
||||
on pg_type.oid = pg_attribute.atttypid
|
||||
where lower(pg_class.relname) = '%s'
|
||||
and pg_constraint.contype='p'
|
||||
""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def indexesSQL(self,tablename=None):
|
||||
sqlcmd = """select
|
||||
i.relname as index_name,
|
||||
case ix.INDISUNIQUE
|
||||
when 't' then 'unique'
|
||||
else ''
|
||||
end as is_unique,
|
||||
a.attname as column_name
|
||||
from
|
||||
pg_class t,
|
||||
pg_class i,
|
||||
pg_index ix,
|
||||
pg_attribute a
|
||||
where
|
||||
t.oid = ix.indrelid
|
||||
and i.oid = ix.indexrelid
|
||||
and a.attrelid = t.oid
|
||||
and a.attnum = ANY(ix.indkey)
|
||||
and t.relkind = 'r'
|
||||
and lower(t.relname) = '%s'
|
||||
order by
|
||||
t.relname,
|
||||
i.relname""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
27
build/lib/sqlor/records.py
Normal file
27
build/lib/sqlor/records.py
Normal file
@ -0,0 +1,27 @@
|
||||
from appPublic.dictObject import DictObject
|
||||
|
||||
class Records:
|
||||
def __init__(self,klass=DictObject):
|
||||
self._records = []
|
||||
self.klass = klass
|
||||
|
||||
def add(self,rec):
|
||||
obj = self.klass(**rec)
|
||||
self._records.append(obj)
|
||||
|
||||
def get(self):
|
||||
return self._records
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
self.start = 0
|
||||
self.end = len(self._records)
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self.start < self.end:
|
||||
d = self._records[self.start]
|
||||
self.start = self.start + 1
|
||||
return d
|
||||
else:
|
||||
raise StopIteration
|
35
build/lib/sqlor/runsql.py
Normal file
35
build/lib/sqlor/runsql.py
Normal file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/python3
|
||||
import sys
|
||||
import codecs
|
||||
from sqlor.dbpools import runSQL
|
||||
import asyncio
|
||||
|
||||
def appinit():
|
||||
if len(sys.argv) < 4:
|
||||
print(f'usage:\n {sys.argv[0]} path dbname sqlfile [k=v ...] \n')
|
||||
sys.exit(1)
|
||||
p = ProgramPath()
|
||||
if len(sys.argv) > 1:
|
||||
p = sys.argv[1]
|
||||
config = getConfig(p)
|
||||
DBPools(config.databases)
|
||||
|
||||
|
||||
async def run(ns):
|
||||
with codecs.open(sys.argv[3], 'r', 'utf-8') as f:
|
||||
sql = f.read()
|
||||
await runSQL(sys.argv[2], sql, ns)
|
||||
|
||||
if __name__ == '__main__':
|
||||
ns = {}
|
||||
for x in sys.argv[3:]:
|
||||
try:
|
||||
k,v = x.split('=')
|
||||
ns.update({k:v})
|
||||
except Exception as e:
|
||||
print(x, 'key-value pair expected')
|
||||
print(e)
|
||||
|
||||
appinit()
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(run(ns))
|
684
build/lib/sqlor/sor.py
Normal file
684
build/lib/sqlor/sor.py
Normal file
@ -0,0 +1,684 @@
|
||||
from traceback import print_exc
|
||||
import os
|
||||
import decimal
|
||||
from asyncio import coroutine
|
||||
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
|
||||
import sys
|
||||
from datetime import datetime, date
|
||||
import codecs
|
||||
import re
|
||||
import json
|
||||
from appPublic.myImport import myImport
|
||||
from appPublic.dictObject import DictObject
|
||||
from appPublic.unicoding import uDict
|
||||
from appPublic.myTE import MyTemplateEngine
|
||||
from appPublic.objectAction import ObjectAction
|
||||
from appPublic.argsConvert import ArgsConvert,ConditionConvert
|
||||
from appPublic.registerfunction import RegisterFunction
|
||||
from appPublic.log import info
|
||||
from .filter import DBFilter
|
||||
|
||||
def db_type_2_py_type(o):
|
||||
if isinstance(o,decimal.Decimal):
|
||||
return float(o)
|
||||
if isinstance(o,datetime):
|
||||
# return '%020d' % int(o.timestamp() * 1000)
|
||||
return str(o)
|
||||
if isinstance(o, date):
|
||||
return '%04d-%02d-%02d' % (o.year, o.month, o.day)
|
||||
return o
|
||||
|
||||
class SQLorException(Exception,object):
|
||||
def __int__(self,**kvs):
|
||||
supper(SQLException,self).__init__(self,**kvs)
|
||||
self.dic = {
|
||||
'response':'error',
|
||||
'errtype':'SQLor',
|
||||
'errmsg':supper(SQLException,self).message,
|
||||
}
|
||||
|
||||
def __str__(self):
|
||||
return 'errtype:%s,errmsg=%s' % (self.dic['errtype'],self.dic['errmsg'])
|
||||
|
||||
def setValues(params,ns):
|
||||
r = ns.get(params,os.getenv(params))
|
||||
return r
|
||||
|
||||
def findNamedParameters(sql):
|
||||
"""
|
||||
return a list of named parameters
|
||||
"""
|
||||
re1 = '\$\{[_a-zA-Z_][a-zA-Z_0-9]*\}'
|
||||
params1 = re.findall(re1,sql)
|
||||
return params1
|
||||
|
||||
|
||||
def uniParams(params1):
|
||||
ret = []
|
||||
for i in params1:
|
||||
if i not in ret:
|
||||
ret.append(i)
|
||||
return ret
|
||||
|
||||
def readsql(fn):
|
||||
f = codecs.open(fn,'r','utf-8')
|
||||
b = f.read()
|
||||
f.close()
|
||||
return b
|
||||
|
||||
class SQLor(object):
|
||||
def __init__(self,dbdesc=None,sqltp = '$[',sqlts = ']$',sqlvp = '${',sqlvs = '}$'):
|
||||
self.conn = None
|
||||
self.cur = None
|
||||
self.async_mode = False
|
||||
self.sqltp = sqltp
|
||||
self.sqlts = sqlts
|
||||
self.sqlvp = sqlvp
|
||||
self.sqlvs = sqlvs
|
||||
self.dbdesc = dbdesc
|
||||
self.dbname = self.dbdesc.get('dbname')
|
||||
if self.dbname:
|
||||
self.dbname = self.dbname.lower()
|
||||
self.writer = None
|
||||
self.convfuncs = {}
|
||||
self.cc = ConditionConvert()
|
||||
self.dataChanged = False
|
||||
self.metadatas={}
|
||||
|
||||
async def get_schema(self):
|
||||
def concat_idx_info(idxs):
|
||||
x = []
|
||||
n = None
|
||||
for i in idxs:
|
||||
if not n or n.index_name != i.index_name:
|
||||
if n:
|
||||
x.append(n)
|
||||
n = i
|
||||
n.column_name = [i.column_name]
|
||||
else:
|
||||
n.column_name.append(i.column_name)
|
||||
return x
|
||||
|
||||
tabs = await self.tables()
|
||||
schemas = []
|
||||
for t in tabs:
|
||||
primary = await self.primary(t.name)
|
||||
# print('primary=', primary)
|
||||
indexes = concat_idx_info(await self.indexes(t.name))
|
||||
fields = await self.fields(t.name)
|
||||
primary_fields = [f.field_name for f in primary]
|
||||
if len(primary_fields)>0:
|
||||
t.primary = [f.field_name for f in primary]
|
||||
x = {}
|
||||
x['summary'] = [t]
|
||||
x['indexes'] = indexes
|
||||
x['fields'] = fields
|
||||
schemas.append(x)
|
||||
return schemas
|
||||
|
||||
def setMeta(self,tablename,meta):
|
||||
self.metadatas[tablename.lower()] = meta
|
||||
|
||||
def getMeta(self,tablename):
|
||||
return self.metadatas.get(tablename.lower(),None)
|
||||
|
||||
def removeMeta(self,tablename):
|
||||
if getMeta(self.tablename):
|
||||
del self.metadatas[tablename.lower()]
|
||||
|
||||
def setCursor(self,async_mode,conn,cur):
|
||||
self.async_mode = async_mode
|
||||
self.conn = conn
|
||||
self.cur = cur
|
||||
|
||||
def getConn(self):
|
||||
return self.conn
|
||||
|
||||
def setConvertFunction(self,typ,func):
|
||||
self.convfuncs.update({typ:func})
|
||||
|
||||
def convert(self,typ,value):
|
||||
if self.convfuncs.get(typ,None) is not None:
|
||||
return self.convfuncs[typ](value)
|
||||
return value
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='sqlor'
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
return ""
|
||||
|
||||
def placeHolder(self,varname,pos=None):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return '?'
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
return [ i.get('value',None) for i in dataList]
|
||||
|
||||
def dataList(self,k,v):
|
||||
a = []
|
||||
a.append({'name':k,'value':v})
|
||||
return a
|
||||
|
||||
def cursor(self):
|
||||
return self.cur
|
||||
|
||||
def recordCnt(self,sql):
|
||||
ret = u"""select count(*) rcnt from (%s) rowcount_table""" % sql
|
||||
return ret
|
||||
|
||||
def sortSQL(self, sql, NS):
|
||||
sort = NS.get('sort',None)
|
||||
if sort is None:
|
||||
return sql
|
||||
if isinstance(sort, list):
|
||||
sort = ','.join(sort)
|
||||
return sql + ' ORDER BY ' + sort
|
||||
|
||||
def pagingSQL(self,sql,paging,NS):
|
||||
"""
|
||||
default it not support paging
|
||||
"""
|
||||
page = int(NS.get(paging['pagename'],1))
|
||||
rows = int(NS.get(paging['rowsname'],80))
|
||||
sort = NS.get(paging.get('sortname','sort'),None)
|
||||
if isinstance(sort, list):
|
||||
sort = ','.join(sort)
|
||||
if not sort:
|
||||
return sql
|
||||
if page < 1:
|
||||
page = 1
|
||||
from_line = (page - 1) * rows
|
||||
end_line = page * rows
|
||||
psql = self.pagingSQLmodel()
|
||||
ns={
|
||||
'from_line':from_line,
|
||||
'end_line':end_line,
|
||||
'rows':rows,
|
||||
'sort':sort
|
||||
}
|
||||
ac = ArgsConvert('$[',']$')
|
||||
psql = ac.convert(psql,ns)
|
||||
retSQL=psql % sql
|
||||
return retSQL
|
||||
|
||||
def filterSQL(self,sql,filters,NS):
|
||||
ac = ArgsConvert('$[',']$')
|
||||
fbs = []
|
||||
for f in filters:
|
||||
vars = ac.findAllVariables(f)
|
||||
if len(vars) > 0:
|
||||
ignoreIt = False
|
||||
for v in vars:
|
||||
if not NS.get(v,False):
|
||||
ignoreIt = True
|
||||
if not ignoreIt:
|
||||
f = ac.convert(f,NS)
|
||||
else:
|
||||
f = '1=1'
|
||||
fbs.append(f)
|
||||
fb = ' '.join(fbs)
|
||||
retsql = u"""select * from (%s) filter_table where %s""" % (sql,fb)
|
||||
return retsql
|
||||
|
||||
async def runVarSQL(self,cursor,sql,NS):
|
||||
"""
|
||||
using a opened cursor to run a SQL statment with variable, the variable is setup in NS namespace
|
||||
return a cursor with data
|
||||
"""
|
||||
markedSQL, datas = self.maskingSQL(sql,NS)
|
||||
datas = self.dataConvert(datas)
|
||||
try:
|
||||
if self.async_mode:
|
||||
return await cursor.execute(markedSQL,datas)
|
||||
else:
|
||||
return cursor.execute(markedSQL,datas)
|
||||
|
||||
except Exception as e:
|
||||
print( "markedSQL=",markedSQL,':',datas,':',e)
|
||||
print_exc()
|
||||
raise e
|
||||
|
||||
def maskingSQL(self,org_sql,NS):
|
||||
"""
|
||||
replace all ${X}$ format variable exception named by '__mainsql__' in sql with '%s',
|
||||
and return the marked sql sentent and variable list
|
||||
sql is a sql statment with variable formated in '${X}$
|
||||
the '__mainsql__' variable use to identify the main sql will outout data.
|
||||
NS is the name space the variable looking for, it is a variable dictionary
|
||||
return (MarkedSQL,list_of_variable)
|
||||
"""
|
||||
sqltextAC = ArgsConvert(self.sqltp,self.sqlts)
|
||||
sqlargsAC = ArgsConvert(self.sqlvp,self.sqlvs)
|
||||
sql1 = sqltextAC.convert(org_sql,NS)
|
||||
cc = ConditionConvert()
|
||||
sql1 = cc.convert(sql1,NS)
|
||||
vars = sqlargsAC.findAllVariables(sql1)
|
||||
phnamespace = {}
|
||||
[phnamespace.update({v:self.placeHolder(v,i)}) for i,v in enumerate(vars)]
|
||||
m_sql = sqlargsAC.convert(sql1,phnamespace)
|
||||
newdata = []
|
||||
for v in vars:
|
||||
if v != '__mainsql__':
|
||||
value = sqlargsAC.getVarValue(v,NS,None)
|
||||
newdata += self.dataList(v,value)
|
||||
|
||||
return (m_sql,newdata)
|
||||
|
||||
def getSqlType(self,sql):
|
||||
"""
|
||||
return one of "qry", "dml" and "ddl"
|
||||
ddl change the database schema
|
||||
dml change the database data
|
||||
qry query data
|
||||
"""
|
||||
|
||||
a = sql.lstrip(' \t\n\r')
|
||||
a = a.lower()
|
||||
al = a.split(' ')
|
||||
if al[0] == 'select':
|
||||
return 'qry'
|
||||
if al[0] in ['update','delete','insert']:
|
||||
return 'dml'
|
||||
return 'ddl'
|
||||
|
||||
async def execute(self,sql,value,callback,**kwargs):
|
||||
sqltype = self.getSqlType(sql)
|
||||
cur = self.cursor()
|
||||
ret = await self.runVarSQL(cur,sql,value)
|
||||
if sqltype == 'qry' and callback is not None:
|
||||
fields = [ i[0].lower() for i in cur.description ]
|
||||
rec = None
|
||||
if self.async_mode:
|
||||
rec = await cur.fetchone()
|
||||
else:
|
||||
rec = cur.fetchone()
|
||||
|
||||
while rec is not None:
|
||||
dic = {}
|
||||
for i in range(len(fields)):
|
||||
dic.update({fields[i] : db_type_2_py_type(rec[i])})
|
||||
dic = DictObject(**dic)
|
||||
callback(dic,**kwargs)
|
||||
if self.async_mode:
|
||||
rec = await cur.fetchone()
|
||||
else:
|
||||
rec = cur.fetchone()
|
||||
if sqltype == 'dml':
|
||||
self.dataChanged = True
|
||||
return ret
|
||||
|
||||
async def executemany(self,sql,values):
|
||||
cur = self.cursor()
|
||||
markedSQL,datas = self.maskingSQL(sql,{})
|
||||
datas = [ self.dataConvert(d) for d in values ]
|
||||
if self.async_mode:
|
||||
await cur.executemany(markedSQL,datas)
|
||||
else:
|
||||
cur.executemany(markedSQL,datas)
|
||||
|
||||
def pivotSQL(self,tablename,rowFields,columnFields,valueFields):
|
||||
def maxValue(columnFields,valueFields,cfvalues):
|
||||
sql = ''
|
||||
for f in valueFields:
|
||||
i = 0
|
||||
for field in columnFields:
|
||||
for v in cfvalues[field]:
|
||||
sql += """
|
||||
,sum(%s_%d) %s_%d""" % (f,i,f,i)
|
||||
i+=1
|
||||
return sql
|
||||
def casewhen(columnFields,valueFields,cfvalues):
|
||||
sql = ''
|
||||
for f in valueFields:
|
||||
i = 0
|
||||
for field in columnFields:
|
||||
for v in cfvalues[field]:
|
||||
if v is None:
|
||||
sql += """,case when %s is null then %s
|
||||
else 0 end as %s_%d -- %s
|
||||
""" % (field,f,f,i,v)
|
||||
else:
|
||||
sql += """,case when trim(%s) = trim('%s') then %s
|
||||
else 0 end as %s_%d -- %s
|
||||
""" % (field,v,f,f,i,v)
|
||||
|
||||
i += 1
|
||||
return sql
|
||||
|
||||
cfvalues={}
|
||||
for field in columnFields:
|
||||
sqlstring = 'select distinct %s from %s' % (field,tablename)
|
||||
v = []
|
||||
self.execute(sqlstring,{},lambda x: v.append(x))
|
||||
cfvalues[field] = [ i[field] for i in v ]
|
||||
|
||||
sql ="""
|
||||
select """ + ','.join(rowFields)
|
||||
sql += maxValue(columnFields,valueFields,cfvalues)
|
||||
sql += """ from
|
||||
(select """ + ','.join(rowFields)
|
||||
sql += casewhen(columnFields,valueFields,cfvalues)
|
||||
sql += """
|
||||
from %s)
|
||||
group by %s""" % (tablename,','.join(rowFields))
|
||||
return sql
|
||||
|
||||
async def pivot(self,desc,tablename,rowFields,columnFields,valueFields):
|
||||
sql = self.pivotSQL(tablename,rowFields,columnFields,valueFields)
|
||||
desc['sql_string'] = sql
|
||||
ret = []
|
||||
return await self.execute(sql,{},lambda x:ret.append(x))
|
||||
|
||||
def isSelectSql(self,sql):
|
||||
return self.getSqlType(sql) == 'qry'
|
||||
|
||||
def getSQLfromDesc(self,desc):
|
||||
sql = ''
|
||||
if 'sql_file' in desc.keys():
|
||||
sql = readsql(desc['sql_file'])
|
||||
else:
|
||||
sql = desc['sql_string']
|
||||
return sql
|
||||
|
||||
async def record_count(self,desc,NS):
|
||||
cnt_desc = {}
|
||||
cnt_desc.update(desc)
|
||||
sql = self.getSQLfromDesc(desc)
|
||||
if desc.get('sql_file',False):
|
||||
del cnt_desc['sql_file']
|
||||
cnt_desc['sql_string'] = self.recordCnt(sql)
|
||||
class Cnt:
|
||||
def __init__(self):
|
||||
self.recs = []
|
||||
def handler(self,rec):
|
||||
self.recs.append(rec)
|
||||
|
||||
c = Cnt()
|
||||
await self.runSQL(cnt_desc,NS,c.handler)
|
||||
t = c.recs[0]['rcnt']
|
||||
return t
|
||||
|
||||
async def runSQLPaging(self,desc,NS):
|
||||
total = await self.record_count(desc,NS)
|
||||
recs = await self.pagingdata(desc,NS)
|
||||
data = {
|
||||
"total":total,
|
||||
"rows":recs
|
||||
}
|
||||
return data
|
||||
|
||||
async def pagingdata(self,desc,NS):
|
||||
paging_desc = {}
|
||||
paging_desc.update(desc)
|
||||
paging_desc.update(
|
||||
{
|
||||
"paging":{
|
||||
"rowsname":"rows",
|
||||
"pagename":"page",
|
||||
"sortname":"sort"
|
||||
}
|
||||
})
|
||||
if desc.get('sortfield',False):
|
||||
NS['sort'] = desc.get('sortfield')
|
||||
sql = self.getSQLfromDesc(desc)
|
||||
if desc.get('sql_file',False):
|
||||
del cnt_desc['sql_file']
|
||||
paging_desc['sql_string'] = self.pagingSQL(sql,
|
||||
paging_desc.get('paging'),NS)
|
||||
|
||||
class Cnt:
|
||||
def __init__(self):
|
||||
self.recs = []
|
||||
def handler(self,rec):
|
||||
self.recs.append(rec)
|
||||
|
||||
c = Cnt()
|
||||
await self.runSQL(paging_desc,NS,c.handler)
|
||||
return c.recs
|
||||
|
||||
async def resultFields(self,desc,NS):
|
||||
NS.update(rows=1,page=1)
|
||||
r = await self.pagingdata(desc,NS)
|
||||
ret = [ {'name':i[0],'type':i[1]} for i in self.cur.description ]
|
||||
return ret
|
||||
|
||||
async def runSQL(self,desc,NS,callback,**kw):
|
||||
class RecordHandler:
|
||||
def __init__(self,ns,name):
|
||||
self.ns = ns
|
||||
self.name = name
|
||||
self.ns[name] = []
|
||||
|
||||
def handler(self,rec):
|
||||
self.ns[self.name].append(rec)
|
||||
|
||||
cur = self.cursor()
|
||||
sql = self.getSQLfromDesc(desc)
|
||||
if self.isSelectSql(sql):
|
||||
if callback is None:
|
||||
klass = desc.get('dataname','dummy')
|
||||
if klass is not None:
|
||||
rh = RecordHandler(NS,klass)
|
||||
callback = rh.handler
|
||||
else:
|
||||
callback = None
|
||||
await self.execute(sql,NS,callback)
|
||||
|
||||
async def sqlExecute(self,desc,NS):
|
||||
return await self.execute(desc,NS,None)
|
||||
|
||||
async def sqlExe(self,sql,ns):
|
||||
ret = []
|
||||
r = await self.execute(sql,ns,
|
||||
callback=lambda x:ret.append(x))
|
||||
sqltype = self.getSqlType(sql)
|
||||
if sqltype == 'dml':
|
||||
return r
|
||||
|
||||
return ret
|
||||
|
||||
async def sqlPaging(self,sql,ns):
|
||||
ret = []
|
||||
dic = {
|
||||
"sql_string":sql
|
||||
}
|
||||
page = ns.get('page')
|
||||
if not page:
|
||||
ns['page'] = 1
|
||||
|
||||
total = await self.record_count(dic,ns)
|
||||
rows = await self.pagingdata(dic,ns)
|
||||
return {
|
||||
'total':total,
|
||||
'rows':rows
|
||||
}
|
||||
|
||||
async def tables(self):
|
||||
sqlstring = self.tablesSQL()
|
||||
ret = []
|
||||
await self.execute(sqlstring,{},lambda x:ret.append(x))
|
||||
return ret
|
||||
|
||||
def indexesSQL(self,tablename):
|
||||
"""
|
||||
record of {
|
||||
index_name,
|
||||
index_type,
|
||||
table_name,
|
||||
column_name
|
||||
}
|
||||
"""
|
||||
return None
|
||||
|
||||
async def indexes(self,tablename=None):
|
||||
sqlstring = self.indexesSQL(tablename.lower())
|
||||
if sqlstring is None:
|
||||
return []
|
||||
recs = []
|
||||
await self.execute(sqlstring,{},lambda x:recs.append(x))
|
||||
return recs
|
||||
|
||||
async def fields(self,tablename=None):
|
||||
sqlstring = self.fieldsSQL(tablename)
|
||||
recs = []
|
||||
await self.execute(sqlstring,{},lambda x:recs.append(x))
|
||||
ret = []
|
||||
for r in recs:
|
||||
r.update({'type':self.db2modelTypeMapping.get(r['type'].lower(),'unknown')})
|
||||
r.update({'name':r['name'].lower()})
|
||||
ret.append(r)
|
||||
return ret
|
||||
|
||||
async def primary(self,tablename):
|
||||
sqlstring = self.pkSQL(tablename)
|
||||
recs = []
|
||||
await self.execute(sqlstring,{},lambda x:recs.append(x))
|
||||
# print('sql=', sqlstring, 'recs=', recs)
|
||||
return recs
|
||||
|
||||
async def fkeys(self,tablename):
|
||||
sqlstring = self.fkSQL(tablename)
|
||||
recs = []
|
||||
await self.execute(sqlstring,{},lambda x:recs.append(x))
|
||||
return recs
|
||||
|
||||
async def createTable(self,tabledesc):
|
||||
te = MyTemplateEngine([],'utf8','utf8')
|
||||
desc = {
|
||||
"sql_string":te.renders(self.ddl_template,tabledesc)
|
||||
}
|
||||
return await self.sqlExecute(desc,{})
|
||||
|
||||
async def getTableDesc(self,tablename):
|
||||
desc = self.getMeta(tablename)
|
||||
if desc:
|
||||
return desc
|
||||
desc = {}
|
||||
summary = [ i for i in await self.tables() if tablename.lower() == i['name'].lower() ]
|
||||
print(f'{summary=}, {tablename=}, {desc=}')
|
||||
pris = await self.primary(tablename)
|
||||
primary = [i['name'] for i in pris ]
|
||||
summary[0]['primary'] = primary
|
||||
desc['summary'] = summary
|
||||
desc['fields'] = await self.fields(tablename=tablename)
|
||||
desc['indexes'] = []
|
||||
idx = {}
|
||||
idxrecs = await self.indexes(tablename)
|
||||
for idxrec in idxrecs:
|
||||
if idxrec['index_name'] == 'primary':
|
||||
continue
|
||||
if idxrec['index_name'] != idx.get('name',None):
|
||||
if idx != {}:
|
||||
desc['indexes'].append(idx)
|
||||
idx = {
|
||||
}
|
||||
idx['name'] = idxrec['index_name']
|
||||
idx['idxtype'] = 'unique' if idxrec['is_unique'] else 'index'
|
||||
idx['idxfields'] = []
|
||||
idx['idxfields'].append(idxrec['column_name'])
|
||||
if idx != {}:
|
||||
desc['indexes'].append(idx)
|
||||
self.setMeta(tablename,desc)
|
||||
return desc
|
||||
|
||||
async def rollback(self):
|
||||
if self.async_mode:
|
||||
await self.conn.rollback()
|
||||
else:
|
||||
self.conn.rollback()
|
||||
self.dataChanged = False
|
||||
|
||||
async def commit(self):
|
||||
if self.async_mode:
|
||||
await self.conn.commit()
|
||||
else:
|
||||
self.conn.commit()
|
||||
self.datachanged = False
|
||||
|
||||
async def I(self,tablename):
|
||||
return await self.getTableDesc(tablename)
|
||||
|
||||
async def C(self,tablename,ns):
|
||||
desc = await self.I(tablename)
|
||||
keys = ns.keys()
|
||||
fields = [ i['name'] for i in desc['fields'] if i['name'] in keys ]
|
||||
fns = ','.join(fields)
|
||||
vfns = ','.join(['${%s}$' % n for n in fields ])
|
||||
sql = 'insert into %s.%s (%s) values (%s)' % (self.dbname, tablename,fns,vfns)
|
||||
rf = RegisterFunction()
|
||||
rfname = f'{self.dbname}:{tablename}:c:before'
|
||||
ret = await rf.exe(rfname, ns)
|
||||
if isinstance(ret, dict):
|
||||
ns.update(ret)
|
||||
r = await self.runSQL({'sql_string':sql},ns.copy(), None)
|
||||
await rf.exe(f'{self.dbname}:{tablename}:c:after', ns)
|
||||
return r
|
||||
|
||||
async def R(self,tablename,ns,filters=None):
|
||||
desc = await self.I(tablename)
|
||||
sql = 'select * from %s.%s' % (self.dbname, tablename.lower())
|
||||
if filters:
|
||||
dbf = DBFilter(filters)
|
||||
sub = dbf.genFilterString(ns)
|
||||
if sub:
|
||||
sql = '%s where %s' % (sql, sub)
|
||||
|
||||
else:
|
||||
fields = [ i['name'] for i in desc['fields'] ]
|
||||
c = [ '%s=${%s}$' % (k,k) for k in ns.keys() if k in fields ]
|
||||
if len(c) > 0:
|
||||
sql = '%s where %s' % (sql,' and '.join(c))
|
||||
|
||||
if 'page' in ns.keys():
|
||||
if not 'sort' in ns.keys():
|
||||
ns['sort'] = desc['summary'][0]['primary'][0]
|
||||
dic = {
|
||||
"sql_string":sql
|
||||
}
|
||||
total = await self.record_count(dic,ns)
|
||||
rows = await self.pagingdata(dic,ns)
|
||||
return {
|
||||
'total':total,
|
||||
'rows':rows
|
||||
}
|
||||
else:
|
||||
if ns.get('sort'):
|
||||
sql = self.sortSQL(sql, ns)
|
||||
return await self.sqlExe(sql,ns)
|
||||
|
||||
async def U(self,tablename,ns):
|
||||
desc = await self.I(tablename)
|
||||
fields = [ i['name'] for i in desc['fields']]
|
||||
condi = [ i for i in desc['summary'][0]['primary']]
|
||||
newData = [ i for i in ns.keys() if i not in condi and i in fields]
|
||||
c = [ '%s = ${%s}$' % (i,i) for i in condi ]
|
||||
u = [ '%s = ${%s}$' % (i,i) for i in newData ]
|
||||
c_str = ' and '.join(c)
|
||||
u_str = ','.join(u)
|
||||
sql = 'update %s.%s set %s where %s' % (self.dbname, tablename,
|
||||
u_str,c_str)
|
||||
rf = RegisterFunction()
|
||||
ret = await rf.exe(f'{self.dbname}:{tablename}:u:before',ns)
|
||||
if isinstance(ret, dict):
|
||||
ns.update(ret)
|
||||
r = await self.runSQL({'sql_string':sql},ns.copy() ,None)
|
||||
await rf.exe(f'{self.dbname}:{tablename}:u:after',ns)
|
||||
return r
|
||||
|
||||
async def D(self,tablename,ns):
|
||||
desc = await self.I(tablename)
|
||||
fields = [ i['name'] for i in desc['fields']]
|
||||
condi = [ i for i in desc['summary'][0]['primary']]
|
||||
c = [ '%s = ${%s}$' % (i,i) for i in condi ]
|
||||
c_str = ' and '.join(c)
|
||||
sql = 'delete from %s.%s where %s' % (self.dbname, tablename,c_str)
|
||||
rf = RegisterFunction()
|
||||
ret = await rf.exe(f'{self.dbname}:{tablename}:d:before', ns)
|
||||
if isinstance(ret, dict):
|
||||
ns.update(ret)
|
||||
r = await self.runSQL({'sql_string':sql},ns,None)
|
||||
ns = await rf.exe(f'{self.dbname}:{tablename}:d:after', ns)
|
||||
return r
|
||||
|
100
build/lib/sqlor/sqlite3or.py
Normal file
100
build/lib/sqlor/sqlite3or.py
Normal file
@ -0,0 +1,100 @@
|
||||
import re
|
||||
from .sor import SQLor
|
||||
|
||||
class SQLite3or(SQLor):
|
||||
db2modelTypeMapping = {
|
||||
'text':'str',
|
||||
'blob':'file',
|
||||
'int':'long',
|
||||
'integer':'long',
|
||||
'real':'float',
|
||||
}
|
||||
model2dbTypemapping = {
|
||||
'date':'text',
|
||||
'time':'text',
|
||||
'timestamp':'text',
|
||||
'str':'text',
|
||||
'char':'text',
|
||||
'short':'int',
|
||||
'long':'int',
|
||||
'float':'real',
|
||||
'text':'text',
|
||||
'file':'blob',
|
||||
}
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='sqlite3'
|
||||
|
||||
def placeHolder(self,varname,pos=None):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return '?'
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
if type(dataList) == type({}):
|
||||
d = [ i for i in dataList.values()]
|
||||
else:
|
||||
d = [ i['value'] for i in dataList]
|
||||
return tuple(d)
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
sql = u"""select * from (%s) order by $[sort]$ limit $[from_line]$,$[end_line]$"""
|
||||
return sql
|
||||
|
||||
def tablesSQL(self):
|
||||
sqlcmd = u"""select name, tbl_name as title from sqlite_master where upper(type) = 'TABLE'"""
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self,tablename):
|
||||
# sqlcmd="""PRAGMA table_info('%s')""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def fields(self,tablename):
|
||||
m = u'(\w+)\(((\d+)(,(\d+)){0,1})\){0,1}'
|
||||
k = re.compile(m)
|
||||
def typesplit(typ):
|
||||
d = k.search(typ)
|
||||
if d is None:
|
||||
return typ,0,0
|
||||
|
||||
return d.group(1),int(d.group(3) if d.group(3) is not None else 0 ),int(d.group(5) if d.group(5) is not None else 0)
|
||||
|
||||
sqlstring = self.fieldsSQL(tablename)
|
||||
recs = []
|
||||
self.execute(sqlstring,callback=lambda x:recs.append(x))
|
||||
for r in recs:
|
||||
t,l,d = typesplit(r['type'])
|
||||
r['type'] = t
|
||||
r['length'] = int(l)
|
||||
r['dec'] = int(d)
|
||||
r['title'] = r['name']
|
||||
ret = []
|
||||
for r in recs:
|
||||
r.update({'type':self.db2modelTypeMapping.get(r['type'].lower(),'text')})
|
||||
r.update({'name':r['name'].lower()})
|
||||
ret.append(r)
|
||||
return ret
|
||||
|
||||
def fkSQL(self,tablename):
|
||||
sqlcmd = ""
|
||||
return sqlcmd
|
||||
|
||||
def fkeys(self,tablename):
|
||||
return []
|
||||
|
||||
def primary(self,tablename):
|
||||
recs = self.fields(tablename)
|
||||
ret = [ {'field':r['name']} for r in recs if r['pk'] == 1 ]
|
||||
return ret
|
||||
|
||||
def pkSQL(self,tablename):
|
||||
sqlcmd = ""
|
||||
return sqlcmd
|
||||
|
||||
def indexesSQL(self,tablename=None):
|
||||
sqlcmd = """select * from sqlite_master
|
||||
where lower(type) = 'index'
|
||||
"""
|
||||
if tablename:
|
||||
sqlcmd += "and lower(tbl_name)='" + tablename.lower() + "' "
|
||||
return sqlcmd
|
2
build/lib/sqlor/version.py
Normal file
2
build/lib/sqlor/version.py
Normal file
@ -0,0 +1,2 @@
|
||||
# fixed sor.py C function bug.
|
||||
__version__ = "0.1.3"
|
26
databases.json
Executable file
26
databases.json
Executable file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"mysql":{
|
||||
"driver":"aiomysql",
|
||||
"async_mode":true,
|
||||
"coding":"utf8",
|
||||
"dbname":"homedata",
|
||||
"maxconn":100,
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"homedata",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"sqlite3":{
|
||||
"driver":"aiosqlite",
|
||||
"async_mode":true,
|
||||
"coding":"utf8",
|
||||
"dbname":"testdb",
|
||||
"maxconn":100,
|
||||
"kwargs":{
|
||||
"database":"./ttttt.db"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
44
dataloader/README.md
Executable file
44
dataloader/README.md
Executable file
@ -0,0 +1,44 @@
|
||||
# dataloader
|
||||
a tool to load data into database from excel file
|
||||
|
||||
## Dependents
|
||||
* [Gadget](https://github.com/yumoqing/gadget)
|
||||
|
||||
You should have a gadget run environment installed before, the dataloader
|
||||
uses gadget conf/config.json file to read the database configuation.
|
||||
|
||||
## Usage
|
||||
change the current folder to gadget running folder(it contains a "conf" folder which config.json file in it), then
|
||||
```
|
||||
datalaoder excel_data_file
|
||||
```
|
||||
|
||||
## Excel file format
|
||||
|
||||
### Specifies the target database
|
||||
use a datasheet to set the sheet name preffix and subffix with '__', examples:
|
||||
"__testdb__" stand for "testdb", "__mydatabase__" stand for "mydatabase",
|
||||
|
||||
### Specifies the target table
|
||||
the table name will use to insert data can be specifies by set the sheet name as the table name
|
||||
|
||||
### Specifies the field name
|
||||
dataloader can inserts data to a table not necesary provide all the fields data, the table's nullable fields can be ignore.
|
||||
|
||||
first row in the sheet is use to specify the fields with data, each cell for one field, value of the cell should be fill in the table's field name.
|
||||
|
||||
### Specifies the data
|
||||
Data start from second row in the sheet, each row for one records
|
||||
|
||||
## Examples
|
||||
there is a kboss database in databases, and the kboss database have two tabel named by 'appcodes' and 'appcodes_kv'
|
||||
|
||||
* Specify database
|
||||
![specify database](./database.png)
|
||||
|
||||
* Specify table appcodes
|
||||
![specify appcodes table](./table1.png)
|
||||
|
||||
* Specify table appcodes_kv
|
||||
![specify table appcodes_kv](./table2.png)
|
||||
|
BIN
dataloader/database.png
Executable file
BIN
dataloader/database.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 233 KiB |
69
dataloader/dataloader.py
Executable file
69
dataloader/dataloader.py
Executable file
@ -0,0 +1,69 @@
|
||||
from appPublic.jsonConfig import getConfig
|
||||
import openpyxl as xlsx
|
||||
import asyncio
|
||||
from sqlor.dbpools import DBPools
|
||||
import aiomysql
|
||||
import aiopg
|
||||
from typeconv import convrec
|
||||
|
||||
class CBObject:
|
||||
def __init__(self,db, name):
|
||||
self.db = db
|
||||
self.tbl = name
|
||||
|
||||
async def handle(self,ws):
|
||||
db = DBPools()
|
||||
info = None
|
||||
async with db.sqlorContext(self.db) as sor:
|
||||
info = await sor.I(self.tbl)
|
||||
for rec in getRecord(ws):
|
||||
async with db.sqlorContext(self.db) as sor:
|
||||
r = [ v for v in rec.values() if v is not None ]
|
||||
if len(r) == 0:
|
||||
continue
|
||||
rec = convrec(info, rec)
|
||||
await sor.C(self.tbl, rec)
|
||||
|
||||
def getRecord(ws):
|
||||
names = []
|
||||
types = []
|
||||
for i,r in enumerate(ws.rows):
|
||||
if i==0:
|
||||
for j,c in enumerate(r):
|
||||
nt = c.value.split(':')
|
||||
if len(nt) < 2:
|
||||
nt.append('')
|
||||
n,t = nt
|
||||
names.append(n)
|
||||
types.append(t)
|
||||
else:
|
||||
dic = {}
|
||||
for j,c in enumerate(r):
|
||||
v = c.value
|
||||
dic[names[j]] = v
|
||||
yield dic
|
||||
|
||||
async def loaddatainexcel(xlsxfile):
|
||||
wb = xlsx.load_workbook(xlsxfile)
|
||||
print(f'{wb.sheetnames=}')
|
||||
dbname = [ i[2:-2] for i in wb.sheetnames if i.startswith('__')][0]
|
||||
print(f'{dbname=}')
|
||||
for name in wb.sheetnames:
|
||||
if name.startswith('__'):
|
||||
continue
|
||||
ws = wb[name]
|
||||
cbobj = CBObject(dbname, name)
|
||||
await cbobj.handle(ws)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
import os
|
||||
p = os.getcwd()
|
||||
config = getConfig(p)
|
||||
print(f'{config.databases=},cwd={p}')
|
||||
DBPools(config.databases)
|
||||
if len(sys.argv) < 2:
|
||||
print('%s xlsxfile' % sys.argv[0])
|
||||
sys.exit(1)
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(loaddatainexcel(sys.argv[1]))
|
4
dataloader/macos/build.sh
Executable file
4
dataloader/macos/build.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
pyinstaller -y --clean dataloader.spec
|
||||
echo "build success, please find the target in dist folder"
|
5448
dataloader/macos/build/dataloader/Analysis-00.toc
Normal file
5448
dataloader/macos/build/dataloader/Analysis-00.toc
Normal file
File diff suppressed because it is too large
Load Diff
771
dataloader/macos/build/dataloader/EXE-00.toc
Normal file
771
dataloader/macos/build/dataloader/EXE-00.toc
Normal file
@ -0,0 +1,771 @@
|
||||
('/Users/ymq/py/sqlor/dataloader/macos/dist/dataloader',
|
||||
True,
|
||||
False,
|
||||
False,
|
||||
None,
|
||||
None,
|
||||
False,
|
||||
False,
|
||||
None,
|
||||
True,
|
||||
True,
|
||||
False,
|
||||
'arm64',
|
||||
None,
|
||||
None,
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/dataloader.pkg',
|
||||
[('PYZ-00.pyz',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/PYZ-00.pyz',
|
||||
'PYZ'),
|
||||
('struct',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/localpycs/struct.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod01_archive',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/localpycs/pyimod01_archive.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod02_importers',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/localpycs/pyimod02_importers.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod03_ctypes',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/localpycs/pyimod03_ctypes.pyc',
|
||||
'PYMODULE'),
|
||||
('pyiboot01_bootstrap',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/loader/pyiboot01_bootstrap.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_inspect',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_inspect.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pkgutil',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_multiprocessing',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_multiprocessing.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pkgres',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgres.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_setuptools',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_setuptools.py',
|
||||
'PYSOURCE'),
|
||||
('dataloader', '/Users/ymq/py/sqlor/dataloader/dataloader.py', 'PYSOURCE'),
|
||||
('Python3',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/../../../../Python3',
|
||||
'BINARY'),
|
||||
('libopenblas64_.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/.dylibs/libopenblas64_.0.dylib',
|
||||
'BINARY'),
|
||||
('libgfortran.5.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/.dylibs/libgfortran.5.dylib',
|
||||
'BINARY'),
|
||||
('libquadmath.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/.dylibs/libquadmath.0.dylib',
|
||||
'BINARY'),
|
||||
('libgcc_s.1.1.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/.dylibs/libgcc_s.1.1.dylib',
|
||||
'BINARY'),
|
||||
('lib-dynload/_lzma.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_lzma.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_bz2.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_bz2.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/zlib.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/zlib.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_datetime.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_datetime.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/math.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/math.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_struct.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_struct.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/grp.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/grp.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/binascii.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/binascii.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/array.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/array.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/select.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/select.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_socket.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_socket.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_statistics.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_statistics.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_contextvars.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_contextvars.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_decimal.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_decimal.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_pickle.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_pickle.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_hashlib.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_hashlib.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_sha3.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_sha3.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_blake2.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_blake2.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_sha256.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_sha256.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_md5.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_md5.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_sha1.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_sha1.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_sha512.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_sha512.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_random.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_random.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_bisect.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_bisect.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_csv.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_csv.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/resource.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/resource.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_posixsubprocess.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_posixsubprocess.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/pyexpat.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/pyexpat.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/termios.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/termios.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/readline.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/readline.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_ssl.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_ssl.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_ctypes.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_ctypes.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_queue.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_queue.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('PIL/_imagingft.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/_imagingft.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/mmap.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/mmap.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('PIL/_webp.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/_webp.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('PIL/_imagingtk.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/_imagingtk.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('PIL/_imagingcms.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/_imagingcms.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_json.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_json.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_opcode.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_opcode.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/core/_multiarray_tests.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/core/_multiarray_tests.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_elementtree.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_elementtree.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('psutil/_psutil_posix.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psutil/_psutil_posix.abi3.so',
|
||||
'EXTENSION'),
|
||||
('psutil/_psutil_osx.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psutil/_psutil_osx.abi3.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/fcntl.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/fcntl.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_curses.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_curses.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/core/_multiarray_umath.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/core/_multiarray_umath.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/linalg/lapack_lite.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/linalg/lapack_lite.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/mtrand.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/mtrand.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_sfc64.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_sfc64.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_philox.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_philox.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_pcg64.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_pcg64.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_mt19937.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_mt19937.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/bit_generator.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/bit_generator.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_generator.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_generator.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_bounded_integers.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_bounded_integers.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_common.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_common.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/fft/_pocketfft_internal.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/fft/_pocketfft_internal.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/linalg/_umath_linalg.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/linalg/_umath_linalg.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('_cffi_backend.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/_cffi_backend.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('PIL/_imaging.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/_imaging.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/unicodedata.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/unicodedata.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_posixshmem.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_posixshmem.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_multiprocessing.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_multiprocessing.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/syslog.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/syslog.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_multibytecodec.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_multibytecodec.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_jp.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_jp.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_kr.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_kr.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_iso2022.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_iso2022.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_cn.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_cn.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_tw.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_tw.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_hk.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_hk.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_scproxy.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_scproxy.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_heapq.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_heapq.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_uuid.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_uuid.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('psycopg2/_psycopg.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/_psycopg.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('nacl/_sodium.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/nacl/_sodium.abi3.so',
|
||||
'EXTENSION'),
|
||||
('bcrypt/_bcrypt.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/bcrypt/_bcrypt.abi3.so',
|
||||
'EXTENSION'),
|
||||
('cryptography/hazmat/bindings/_openssl.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography/hazmat/bindings/_openssl.abi3.so',
|
||||
'EXTENSION'),
|
||||
('cryptography/hazmat/bindings/_rust.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography/hazmat/bindings/_rust.abi3.so',
|
||||
'EXTENSION'),
|
||||
('ujson.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/ujson.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('markupsafe/_speedups.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/markupsafe/_speedups.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_asyncio.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_asyncio.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/etree.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/etree.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/_elementpath.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/_elementpath.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/sax.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/sax.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/objectify.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/objectify.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('charset_normalizer/md__mypyc.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/charset_normalizer/md__mypyc.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('charset_normalizer/md.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/charset_normalizer/md.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('cchardet/_cchardet.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cchardet/_cchardet.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/html/diff.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/html/diff.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/html/clean.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/html/clean.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/builder.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/builder.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('libharfbuzz.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libharfbuzz.0.dylib',
|
||||
'BINARY'),
|
||||
('libfreetype.6.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libfreetype.6.dylib',
|
||||
'BINARY'),
|
||||
('libwebpdemux.2.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libwebpdemux.2.dylib',
|
||||
'BINARY'),
|
||||
('libwebpmux.3.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libwebpmux.3.dylib',
|
||||
'BINARY'),
|
||||
('libwebp.7.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libwebp.7.dylib',
|
||||
'BINARY'),
|
||||
('liblcms2.2.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/liblcms2.2.dylib',
|
||||
'BINARY'),
|
||||
('libtiff.6.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libtiff.6.dylib',
|
||||
'BINARY'),
|
||||
('libz.1.2.13.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libz.1.2.13.dylib',
|
||||
'BINARY'),
|
||||
('libxcb.1.1.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libxcb.1.1.0.dylib',
|
||||
'BINARY'),
|
||||
('libopenjp2.2.5.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libopenjp2.2.5.0.dylib',
|
||||
'BINARY'),
|
||||
('libcrypto.1.1.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libcrypto.1.1.dylib',
|
||||
'BINARY'),
|
||||
('libpq.5.15.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libpq.5.15.dylib',
|
||||
'BINARY'),
|
||||
('libssl.1.1.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libssl.1.1.dylib',
|
||||
'BINARY'),
|
||||
('libbrotlidec.1.0.9.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libbrotlidec.1.0.9.dylib',
|
||||
'BINARY'),
|
||||
('libpng16.16.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libpng16.16.dylib',
|
||||
'BINARY'),
|
||||
('liblzma.5.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/liblzma.5.dylib',
|
||||
'BINARY'),
|
||||
('libXau.6.0.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libXau.6.0.0.dylib',
|
||||
'BINARY'),
|
||||
('libgssapi_krb5.2.2.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libgssapi_krb5.2.2.dylib',
|
||||
'BINARY'),
|
||||
('libbrotlicommon.1.0.9.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libbrotlicommon.1.0.9.dylib',
|
||||
'BINARY'),
|
||||
('libcom_err.3.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libcom_err.3.0.dylib',
|
||||
'BINARY'),
|
||||
('libkrb5.3.3.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libkrb5.3.3.dylib',
|
||||
'BINARY'),
|
||||
('libk5crypto.3.1.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libk5crypto.3.1.dylib',
|
||||
'BINARY'),
|
||||
('libkrb5support.1.1.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libkrb5support.1.1.dylib',
|
||||
'BINARY'),
|
||||
('base_library.zip',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/base_library.zip',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/small-white/framing.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/small-white/framing.css',
|
||||
'DATA'),
|
||||
('docutils/writers/html4css1/template.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html4css1/template.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/odf_odt/styles.odt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/odf_odt/styles.odt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/s5defs.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/s5defs.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamsr.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamsr.txt',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/LICENSE',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/LICENSE',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/mmlextra.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/mmlextra.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/big-black/__base__',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/big-black/__base__',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/slides.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/slides.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isocyr1.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isocyr1.txt',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/RNG2Schtrn.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/RNG2Schtrn.xsl',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_skeleton_for_xslt1.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_skeleton_for_xslt1.xsl',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/medium-white/framing.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/medium-white/framing.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomfrk.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomfrk.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isobox.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isobox.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/small-black/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/small-black/pretty.css',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/responsive.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/responsive.css',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/print.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/print.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/mmlalias.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/mmlalias.txt',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/top_level.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/top_level.txt',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/top_level.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/top_level.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isolat2.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isolat2.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isolat1.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isolat1.txt',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/INSTALLER',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/INSTALLER',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/WHEEL',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/WHEEL',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomscr.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomscr.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/README.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/README.txt',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/METADATA',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/METADATA',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_dsdl_include.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_dsdl_include.xsl',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/small-black/__base__',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/small-black/__base__',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/medium-black/__base__',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/medium-black/__base__',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/big-white/framing.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/big-white/framing.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamsb.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamsb.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamsc.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamsc.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/html4css1/html4css1.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html4css1/html4css1.css',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/LICENSE.PSF',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/LICENSE.PSF',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_message.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_message.xsl',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamso.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamso.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/mmlextra-wide.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/mmlextra-wide.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/pep_html/pep.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/pep_html/pep.css',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/medium-black/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/medium-black/pretty.css',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/WHEEL',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/WHEEL',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/opera.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/opera.css',
|
||||
'DATA'),
|
||||
('nacl/py.typed',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/nacl/py.typed',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/small-white/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/small-white/pretty.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isotech.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isotech.txt',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/readme.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/readme.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isocyr2.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isocyr2.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isogrk4-wide.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isogrk4-wide.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/latex2e/xelatex.tex',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/latex2e/xelatex.tex',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/template.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/template.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/tuftig.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/tuftig.css',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/LICENSE.APACHE',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/LICENSE.APACHE',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomfrk-wide.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomfrk-wide.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/README.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/README.txt',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/RECORD',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/RECORD',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/outline.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/outline.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isogrk2.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isogrk2.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/big-black/framing.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/big-black/framing.css',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/minimal.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/minimal.css',
|
||||
'DATA'),
|
||||
('docutils/writers/latex2e/titlingpage.tex',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/latex2e/titlingpage.tex',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/METADATA',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/METADATA',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/xhtml1-special.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/xhtml1-special.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isogrk1.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isogrk1.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/latex2e/docutils.sty',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/latex2e/docutils.sty',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/rng/iso-schematron.rng',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/rng/iso-schematron.rng',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isogrk4.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isogrk4.txt',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/REQUESTED',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/REQUESTED',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/medium-white/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/medium-white/pretty.css',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/math.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/math.css',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/pretty.css',
|
||||
'DATA'),
|
||||
('docutils/writers/latex2e/default.tex',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/latex2e/default.tex',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/xhtml1-symbol.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/xhtml1-symbol.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/framing.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/framing.css',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/big-white/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/big-white/pretty.css',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/INSTALLER',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/INSTALLER',
|
||||
'DATA'),
|
||||
('docutils/writers/latex2e/titlepage.tex',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/latex2e/titlepage.tex',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/XSD2Schtrn.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/XSD2Schtrn.xsl',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomopf-wide.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomopf-wide.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isonum.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isonum.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamsn.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamsn.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamsa.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamsa.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomscr-wide.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomscr-wide.txt',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/RECORD',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/RECORD',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/LICENSE',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/LICENSE',
|
||||
'DATA'),
|
||||
('docutils/writers/pep_html/template.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/pep_html/template.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/plain.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/plain.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isodia.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isodia.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/slides.js',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/slides.js',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/xhtml1-lat1.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/xhtml1-lat1.txt',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/LICENSE.BSD',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/LICENSE.BSD',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/s5-core.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/s5-core.css',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_svrl_for_xslt1.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_svrl_for_xslt1.xsl',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/big-black/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/big-black/pretty.css',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_abstract_expand.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_abstract_expand.xsl',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomopf.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomopf.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isogrk3.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isogrk3.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isopub.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isopub.txt',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/RECORD',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/RECORD',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/INSTALLER',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/INSTALLER',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/RECORD.jws',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/RECORD.jws',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/REQUESTED',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/REQUESTED',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/LICENSE',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/LICENSE',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/top_level.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/top_level.txt',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/LICENSE.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/LICENSE.txt',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/WHEEL',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/WHEEL',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/DESCRIPTION.rst',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/DESCRIPTION.rst',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/entry_points.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/entry_points.txt',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/top_level.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/top_level.txt',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/INSTALLER',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/INSTALLER',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/entry_points.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/entry_points.txt',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/METADATA',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/METADATA',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/RECORD',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/RECORD',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/WHEEL',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/WHEEL',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/METADATA',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/METADATA',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/metadata.json',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/metadata.json',
|
||||
'DATA')],
|
||||
[],
|
||||
False,
|
||||
False,
|
||||
1692345757,
|
||||
[('run',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/bootloader/Darwin-64bit/run',
|
||||
'EXECUTABLE')])
|
764
dataloader/macos/build/dataloader/PKG-00.toc
Normal file
764
dataloader/macos/build/dataloader/PKG-00.toc
Normal file
@ -0,0 +1,764 @@
|
||||
('/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/dataloader.pkg',
|
||||
{'BINARY': True,
|
||||
'DATA': True,
|
||||
'EXECUTABLE': True,
|
||||
'EXTENSION': True,
|
||||
'PYMODULE': True,
|
||||
'PYSOURCE': True,
|
||||
'PYZ': False,
|
||||
'SPLASH': True},
|
||||
[('PYZ-00.pyz',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/PYZ-00.pyz',
|
||||
'PYZ'),
|
||||
('struct',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/localpycs/struct.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod01_archive',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/localpycs/pyimod01_archive.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod02_importers',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/localpycs/pyimod02_importers.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod03_ctypes',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/localpycs/pyimod03_ctypes.pyc',
|
||||
'PYMODULE'),
|
||||
('pyiboot01_bootstrap',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/loader/pyiboot01_bootstrap.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_inspect',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_inspect.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pkgutil',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_multiprocessing',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_multiprocessing.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pkgres',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgres.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_setuptools',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_setuptools.py',
|
||||
'PYSOURCE'),
|
||||
('dataloader', '/Users/ymq/py/sqlor/dataloader/dataloader.py', 'PYSOURCE'),
|
||||
('Python3',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/../../../../Python3',
|
||||
'BINARY'),
|
||||
('libopenblas64_.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/.dylibs/libopenblas64_.0.dylib',
|
||||
'BINARY'),
|
||||
('libgfortran.5.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/.dylibs/libgfortran.5.dylib',
|
||||
'BINARY'),
|
||||
('libquadmath.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/.dylibs/libquadmath.0.dylib',
|
||||
'BINARY'),
|
||||
('libgcc_s.1.1.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/.dylibs/libgcc_s.1.1.dylib',
|
||||
'BINARY'),
|
||||
('lib-dynload/_lzma.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_lzma.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_bz2.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_bz2.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/zlib.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/zlib.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_datetime.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_datetime.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/math.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/math.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_struct.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_struct.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/grp.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/grp.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/binascii.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/binascii.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/array.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/array.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/select.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/select.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_socket.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_socket.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_statistics.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_statistics.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_contextvars.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_contextvars.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_decimal.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_decimal.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_pickle.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_pickle.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_hashlib.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_hashlib.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_sha3.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_sha3.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_blake2.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_blake2.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_sha256.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_sha256.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_md5.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_md5.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_sha1.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_sha1.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_sha512.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_sha512.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_random.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_random.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_bisect.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_bisect.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_csv.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_csv.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/resource.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/resource.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_posixsubprocess.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_posixsubprocess.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/pyexpat.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/pyexpat.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/termios.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/termios.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/readline.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/readline.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_ssl.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_ssl.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_ctypes.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_ctypes.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_queue.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_queue.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('PIL/_imagingft.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/_imagingft.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/mmap.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/mmap.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('PIL/_webp.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/_webp.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('PIL/_imagingtk.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/_imagingtk.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('PIL/_imagingcms.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/_imagingcms.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_json.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_json.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_opcode.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_opcode.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/core/_multiarray_tests.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/core/_multiarray_tests.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_elementtree.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_elementtree.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('psutil/_psutil_posix.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psutil/_psutil_posix.abi3.so',
|
||||
'EXTENSION'),
|
||||
('psutil/_psutil_osx.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psutil/_psutil_osx.abi3.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/fcntl.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/fcntl.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_curses.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_curses.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/core/_multiarray_umath.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/core/_multiarray_umath.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/linalg/lapack_lite.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/linalg/lapack_lite.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/mtrand.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/mtrand.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_sfc64.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_sfc64.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_philox.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_philox.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_pcg64.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_pcg64.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_mt19937.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_mt19937.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/bit_generator.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/bit_generator.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_generator.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_generator.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_bounded_integers.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_bounded_integers.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/random/_common.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/random/_common.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/fft/_pocketfft_internal.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/fft/_pocketfft_internal.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('numpy/linalg/_umath_linalg.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/numpy/linalg/_umath_linalg.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('_cffi_backend.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/_cffi_backend.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('PIL/_imaging.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/_imaging.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/unicodedata.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/unicodedata.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_posixshmem.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_posixshmem.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_multiprocessing.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_multiprocessing.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/syslog.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/syslog.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_multibytecodec.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_multibytecodec.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_jp.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_jp.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_kr.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_kr.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_iso2022.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_iso2022.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_cn.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_cn.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_tw.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_tw.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_codecs_hk.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_codecs_hk.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_scproxy.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_scproxy.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_heapq.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_heapq.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_uuid.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_uuid.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('psycopg2/_psycopg.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/_psycopg.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('nacl/_sodium.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/nacl/_sodium.abi3.so',
|
||||
'EXTENSION'),
|
||||
('bcrypt/_bcrypt.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/bcrypt/_bcrypt.abi3.so',
|
||||
'EXTENSION'),
|
||||
('cryptography/hazmat/bindings/_openssl.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography/hazmat/bindings/_openssl.abi3.so',
|
||||
'EXTENSION'),
|
||||
('cryptography/hazmat/bindings/_rust.abi3.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography/hazmat/bindings/_rust.abi3.so',
|
||||
'EXTENSION'),
|
||||
('ujson.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/ujson.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('markupsafe/_speedups.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/markupsafe/_speedups.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lib-dynload/_asyncio.cpython-39-darwin.so',
|
||||
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/lib-dynload/_asyncio.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/etree.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/etree.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/_elementpath.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/_elementpath.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/sax.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/sax.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/objectify.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/objectify.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('charset_normalizer/md__mypyc.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/charset_normalizer/md__mypyc.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('charset_normalizer/md.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/charset_normalizer/md.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('cchardet/_cchardet.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cchardet/_cchardet.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/html/diff.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/html/diff.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/html/clean.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/html/clean.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('lxml/builder.cpython-39-darwin.so',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/builder.cpython-39-darwin.so',
|
||||
'EXTENSION'),
|
||||
('libharfbuzz.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libharfbuzz.0.dylib',
|
||||
'BINARY'),
|
||||
('libfreetype.6.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libfreetype.6.dylib',
|
||||
'BINARY'),
|
||||
('libwebpdemux.2.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libwebpdemux.2.dylib',
|
||||
'BINARY'),
|
||||
('libwebpmux.3.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libwebpmux.3.dylib',
|
||||
'BINARY'),
|
||||
('libwebp.7.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libwebp.7.dylib',
|
||||
'BINARY'),
|
||||
('liblcms2.2.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/liblcms2.2.dylib',
|
||||
'BINARY'),
|
||||
('libtiff.6.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libtiff.6.dylib',
|
||||
'BINARY'),
|
||||
('libz.1.2.13.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libz.1.2.13.dylib',
|
||||
'BINARY'),
|
||||
('libxcb.1.1.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libxcb.1.1.0.dylib',
|
||||
'BINARY'),
|
||||
('libopenjp2.2.5.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libopenjp2.2.5.0.dylib',
|
||||
'BINARY'),
|
||||
('libcrypto.1.1.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libcrypto.1.1.dylib',
|
||||
'BINARY'),
|
||||
('libpq.5.15.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libpq.5.15.dylib',
|
||||
'BINARY'),
|
||||
('libssl.1.1.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libssl.1.1.dylib',
|
||||
'BINARY'),
|
||||
('libbrotlidec.1.0.9.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libbrotlidec.1.0.9.dylib',
|
||||
'BINARY'),
|
||||
('libpng16.16.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libpng16.16.dylib',
|
||||
'BINARY'),
|
||||
('liblzma.5.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/liblzma.5.dylib',
|
||||
'BINARY'),
|
||||
('libXau.6.0.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libXau.6.0.0.dylib',
|
||||
'BINARY'),
|
||||
('libgssapi_krb5.2.2.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libgssapi_krb5.2.2.dylib',
|
||||
'BINARY'),
|
||||
('libbrotlicommon.1.0.9.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/PIL/.dylibs/libbrotlicommon.1.0.9.dylib',
|
||||
'BINARY'),
|
||||
('libcom_err.3.0.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libcom_err.3.0.dylib',
|
||||
'BINARY'),
|
||||
('libkrb5.3.3.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libkrb5.3.3.dylib',
|
||||
'BINARY'),
|
||||
('libk5crypto.3.1.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libk5crypto.3.1.dylib',
|
||||
'BINARY'),
|
||||
('libkrb5support.1.1.dylib',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/psycopg2/.dylibs/libkrb5support.1.1.dylib',
|
||||
'BINARY'),
|
||||
('base_library.zip',
|
||||
'/Users/ymq/py/sqlor/dataloader/macos/build/dataloader/base_library.zip',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/small-white/framing.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/small-white/framing.css',
|
||||
'DATA'),
|
||||
('docutils/writers/html4css1/template.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html4css1/template.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/odf_odt/styles.odt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/odf_odt/styles.odt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/s5defs.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/s5defs.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamsr.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamsr.txt',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/LICENSE',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/LICENSE',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/mmlextra.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/mmlextra.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/big-black/__base__',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/big-black/__base__',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/slides.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/slides.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isocyr1.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isocyr1.txt',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/RNG2Schtrn.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/RNG2Schtrn.xsl',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_skeleton_for_xslt1.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_skeleton_for_xslt1.xsl',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/medium-white/framing.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/medium-white/framing.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomfrk.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomfrk.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isobox.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isobox.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/small-black/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/small-black/pretty.css',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/responsive.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/responsive.css',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/print.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/print.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/mmlalias.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/mmlalias.txt',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/top_level.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/top_level.txt',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/top_level.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/top_level.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isolat2.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isolat2.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isolat1.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isolat1.txt',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/INSTALLER',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/INSTALLER',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/WHEEL',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/WHEEL',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomscr.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomscr.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/README.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/README.txt',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/METADATA',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/METADATA',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_dsdl_include.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_dsdl_include.xsl',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/small-black/__base__',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/small-black/__base__',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/medium-black/__base__',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/medium-black/__base__',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/big-white/framing.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/big-white/framing.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamsb.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamsb.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamsc.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamsc.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/html4css1/html4css1.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html4css1/html4css1.css',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/LICENSE.PSF',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/LICENSE.PSF',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_message.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_message.xsl',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamso.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamso.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/mmlextra-wide.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/mmlextra-wide.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/pep_html/pep.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/pep_html/pep.css',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/medium-black/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/medium-black/pretty.css',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/WHEEL',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/WHEEL',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/opera.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/opera.css',
|
||||
'DATA'),
|
||||
('nacl/py.typed',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/nacl/py.typed',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/small-white/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/small-white/pretty.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isotech.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isotech.txt',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/readme.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/readme.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isocyr2.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isocyr2.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isogrk4-wide.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isogrk4-wide.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/latex2e/xelatex.tex',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/latex2e/xelatex.tex',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/template.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/template.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/tuftig.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/tuftig.css',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/LICENSE.APACHE',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/LICENSE.APACHE',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomfrk-wide.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomfrk-wide.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/README.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/README.txt',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/RECORD',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/RECORD',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/outline.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/outline.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isogrk2.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isogrk2.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/big-black/framing.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/big-black/framing.css',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/minimal.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/minimal.css',
|
||||
'DATA'),
|
||||
('docutils/writers/latex2e/titlingpage.tex',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/latex2e/titlingpage.tex',
|
||||
'DATA'),
|
||||
('importlib_metadata-6.8.0.dist-info/METADATA',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/importlib_metadata-6.8.0.dist-info/METADATA',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/xhtml1-special.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/xhtml1-special.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isogrk1.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isogrk1.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/latex2e/docutils.sty',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/latex2e/docutils.sty',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/rng/iso-schematron.rng',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/rng/iso-schematron.rng',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isogrk4.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isogrk4.txt',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/REQUESTED',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/REQUESTED',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/medium-white/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/medium-white/pretty.css',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/math.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/math.css',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/pretty.css',
|
||||
'DATA'),
|
||||
('docutils/writers/latex2e/default.tex',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/latex2e/default.tex',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/xhtml1-symbol.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/xhtml1-symbol.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/framing.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/framing.css',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/big-white/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/big-white/pretty.css',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/INSTALLER',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/INSTALLER',
|
||||
'DATA'),
|
||||
('docutils/writers/latex2e/titlepage.tex',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/latex2e/titlepage.tex',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/XSD2Schtrn.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/XSD2Schtrn.xsl',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomopf-wide.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomopf-wide.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isonum.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isonum.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamsn.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamsn.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isoamsa.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isoamsa.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomscr-wide.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomscr-wide.txt',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/RECORD',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/RECORD',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/LICENSE',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/LICENSE',
|
||||
'DATA'),
|
||||
('docutils/writers/pep_html/template.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/pep_html/template.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/html5_polyglot/plain.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/html5_polyglot/plain.css',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isodia.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isodia.txt',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/slides.js',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/slides.js',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/xhtml1-lat1.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/xhtml1-lat1.txt',
|
||||
'DATA'),
|
||||
('cryptography-39.0.1.dist-info/LICENSE.BSD',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/cryptography-39.0.1.dist-info/LICENSE.BSD',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/default/s5-core.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/default/s5-core.css',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_svrl_for_xslt1.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_svrl_for_xslt1.xsl',
|
||||
'DATA'),
|
||||
('docutils/writers/s5_html/themes/big-black/pretty.css',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/writers/s5_html/themes/big-black/pretty.css',
|
||||
'DATA'),
|
||||
('lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_abstract_expand.xsl',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_abstract_expand.xsl',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isomopf.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isomopf.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isogrk3.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isogrk3.txt',
|
||||
'DATA'),
|
||||
('docutils/parsers/rst/include/isopub.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/docutils/parsers/rst/include/isopub.txt',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/RECORD',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/RECORD',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/INSTALLER',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/INSTALLER',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/RECORD.jws',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/RECORD.jws',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/REQUESTED',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/REQUESTED',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/LICENSE',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/LICENSE',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/top_level.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/top_level.txt',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/LICENSE.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/LICENSE.txt',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/WHEEL',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/WHEEL',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/DESCRIPTION.rst',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/DESCRIPTION.rst',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/entry_points.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/entry_points.txt',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/top_level.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/top_level.txt',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/INSTALLER',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/INSTALLER',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/entry_points.txt',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/entry_points.txt',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/METADATA',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/METADATA',
|
||||
'DATA'),
|
||||
('setuptools-67.1.0.dist-info/RECORD',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/setuptools-67.1.0.dist-info/RECORD',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/WHEEL',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/WHEEL',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/METADATA',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/METADATA',
|
||||
'DATA'),
|
||||
('wheel-0.24.0.dist-info/metadata.json',
|
||||
'/Users/ymq/py3/lib/python3.9/site-packages/wheel-0.24.0.dist-info/metadata.json',
|
||||
'DATA')],
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
[],
|
||||
'arm64',
|
||||
None,
|
||||
None)
|
BIN
dataloader/macos/build/dataloader/PYZ-00.pyz
Normal file
BIN
dataloader/macos/build/dataloader/PYZ-00.pyz
Normal file
Binary file not shown.
4697
dataloader/macos/build/dataloader/PYZ-00.toc
Normal file
4697
dataloader/macos/build/dataloader/PYZ-00.toc
Normal file
File diff suppressed because it is too large
Load Diff
BIN
dataloader/macos/build/dataloader/base_library.zip
Normal file
BIN
dataloader/macos/build/dataloader/base_library.zip
Normal file
Binary file not shown.
BIN
dataloader/macos/build/dataloader/dataloader.pkg
Normal file
BIN
dataloader/macos/build/dataloader/dataloader.pkg
Normal file
Binary file not shown.
BIN
dataloader/macos/build/dataloader/localpycs/pyimod01_archive.pyc
Normal file
BIN
dataloader/macos/build/dataloader/localpycs/pyimod01_archive.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
dataloader/macos/build/dataloader/localpycs/pyimod03_ctypes.pyc
Normal file
BIN
dataloader/macos/build/dataloader/localpycs/pyimod03_ctypes.pyc
Normal file
Binary file not shown.
BIN
dataloader/macos/build/dataloader/localpycs/struct.pyc
Normal file
BIN
dataloader/macos/build/dataloader/localpycs/struct.pyc
Normal file
Binary file not shown.
205
dataloader/macos/build/dataloader/warn-dataloader.txt
Normal file
205
dataloader/macos/build/dataloader/warn-dataloader.txt
Normal file
@ -0,0 +1,205 @@
|
||||
|
||||
This file lists modules PyInstaller was not able to find. This does not
|
||||
necessarily mean this module is required for running your program. Python and
|
||||
Python 3rd-party packages include a lot of conditional or optional modules. For
|
||||
example the module 'ntpath' only exists on Windows, whereas the module
|
||||
'posixpath' only exists on Posix systems.
|
||||
|
||||
Types if import:
|
||||
* top-level: imported at the top-level - look at these first
|
||||
* conditional: imported within an if-statement
|
||||
* delayed: imported within a function
|
||||
* optional: imported within a try-except-statement
|
||||
|
||||
IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for
|
||||
tracking down the missing module yourself. Thanks!
|
||||
|
||||
missing module named pep517 - imported by importlib.metadata (delayed)
|
||||
missing module named 'org.python' - imported by copy (optional), xml.sax (delayed, conditional)
|
||||
missing module named org - imported by pickle (optional)
|
||||
missing module named winreg - imported by importlib._bootstrap_external (conditional), mimetypes (optional), urllib.request (delayed, conditional, optional), platform (delayed, optional), distutils.msvc9compiler (top-level), distutils._msvccompiler (top-level), pkg_resources._vendor.platformdirs.windows (delayed, optional), setuptools.msvc (conditional), setuptools._distutils._msvccompiler (top-level), setuptools._distutils.msvc9compiler (top-level), setuptools._distutils.msvccompiler (optional), pygments.formatters.img (optional)
|
||||
missing module named nt - imported by shutil (conditional), importlib._bootstrap_external (conditional), ntpath (optional), pathlib (conditional), os (delayed, conditional, optional), ctypes (delayed, conditional)
|
||||
missing module named _frozen_importlib_external - imported by importlib._bootstrap (delayed), importlib (optional), importlib.abc (optional), zipimport (top-level)
|
||||
excluded module named _frozen_importlib - imported by importlib (optional), importlib.abc (optional), zipimport (top-level)
|
||||
missing module named _winapi - imported by encodings (delayed, conditional, optional), subprocess (optional), multiprocessing.connection (optional), multiprocessing.spawn (delayed, conditional), multiprocessing.reduction (conditional), multiprocessing.shared_memory (conditional), multiprocessing.heap (conditional), multiprocessing.popen_spawn_win32 (top-level), asyncio.windows_events (top-level), asyncio.windows_utils (top-level)
|
||||
missing module named msvcrt - imported by subprocess (optional), getpass (optional), multiprocessing.spawn (delayed, conditional), multiprocessing.popen_spawn_win32 (top-level), asyncio.windows_events (top-level), asyncio.windows_utils (top-level)
|
||||
missing module named vms_lib - imported by platform (delayed, optional)
|
||||
missing module named 'java.lang' - imported by platform (delayed, optional), xml.sax._exceptions (conditional)
|
||||
missing module named java - imported by platform (delayed)
|
||||
missing module named _winreg - imported by platform (delayed, optional), pygments.formatters.img (optional)
|
||||
missing module named win32con - imported by setuptools._distutils.msvccompiler (optional)
|
||||
missing module named win32api - imported by setuptools._distutils.msvccompiler (optional)
|
||||
missing module named 'distutils._log' - imported by setuptools._distutils.command.bdist_dumb (top-level), setuptools._distutils.command.bdist_rpm (top-level), setuptools._distutils.command.build_clib (top-level), setuptools._distutils.command.build_ext (top-level), setuptools._distutils.command.build_py (top-level), setuptools._distutils.command.build_scripts (top-level), setuptools._distutils.command.clean (top-level), setuptools._distutils.command.config (top-level), setuptools._distutils.command.install (top-level), setuptools._distutils.command.install_scripts (top-level), setuptools._distutils.command.register (top-level), setuptools._distutils.command.sdist (top-level)
|
||||
missing module named usercustomize - imported by site (delayed, optional)
|
||||
missing module named sitecustomize - imported by site (delayed, optional)
|
||||
missing module named _manylinux - imported by packaging._manylinux (delayed, optional), setuptools._vendor.packaging._manylinux (delayed, optional), pkg_resources._vendor.packaging._manylinux (delayed, optional)
|
||||
missing module named jnius - imported by pkg_resources._vendor.platformdirs.android (delayed, optional)
|
||||
missing module named platformdirs - imported by pkg_resources._vendor.platformdirs.__main__ (top-level)
|
||||
missing module named 'pkg_resources.extern.importlib_resources' - imported by pkg_resources._vendor.jaraco.text (optional)
|
||||
missing module named 'typing.io' - imported by importlib.resources (top-level)
|
||||
missing module named 'pkg_resources.extern.more_itertools' - imported by pkg_resources._vendor.jaraco.functools (top-level)
|
||||
missing module named pkg_resources.extern.packaging - imported by pkg_resources.extern (top-level), pkg_resources (top-level)
|
||||
missing module named pkg_resources.extern.platformdirs - imported by pkg_resources.extern (top-level), pkg_resources (top-level)
|
||||
missing module named 'pkg_resources.extern.jaraco' - imported by pkg_resources (top-level), pkg_resources._vendor.jaraco.text (top-level)
|
||||
missing module named ctags - imported by pygments.formatters.html (optional)
|
||||
missing module named pygments.lexers.PrologLexer - imported by pygments.lexers (top-level), pygments.lexers.cplint (top-level)
|
||||
missing module named PIL._imagingagg - imported by PIL (delayed, conditional, optional), PIL.ImageDraw (delayed, conditional, optional)
|
||||
missing module named olefile - imported by PIL.FpxImagePlugin (top-level), PIL.MicImagePlugin (top-level)
|
||||
missing module named psutil._psutil_aix - imported by psutil (top-level), psutil._psaix (top-level)
|
||||
missing module named psutil._psutil_sunos - imported by psutil (top-level), psutil._pssunos (top-level)
|
||||
missing module named psutil._psutil_bsd - imported by psutil (top-level), psutil._psbsd (top-level)
|
||||
missing module named _psutil_windows - imported by psutil._pswindows (top-level)
|
||||
missing module named psutil._psutil_windows - imported by psutil (conditional, optional), psutil._pswindows (optional)
|
||||
missing module named psutil._psutil_linux - imported by psutil (top-level), psutil._pslinux (top-level)
|
||||
missing module named dummy_threading - imported by psutil._compat (optional)
|
||||
missing module named _dummy_thread - imported by numpy.core.arrayprint (optional), cffi.lock (conditional, optional)
|
||||
missing module named numpy.core.result_type - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.float_ - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.number - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.object_ - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.all - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.bool_ - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.inf - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.array2string - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.lib.imag - imported by numpy.lib (delayed), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.lib.real - imported by numpy.lib (delayed), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.lib.iscomplexobj - imported by numpy.lib (delayed), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.signbit - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.isscalar - imported by numpy.core (delayed), numpy.testing._private.utils (delayed), numpy.lib.polynomial (top-level)
|
||||
missing module named win32pdh - imported by numpy.testing._private.utils (delayed, conditional)
|
||||
missing module named numpy.core.isinf - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.errstate - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.isfinite - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.isnan - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy.core.array - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (top-level), numpy.lib.polynomial (top-level)
|
||||
missing module named numpy.core.isnat - imported by numpy.core (top-level), numpy.testing._private.utils (top-level)
|
||||
missing module named numpy.core.ndarray - imported by numpy.core (top-level), numpy.testing._private.utils (top-level), numpy.lib.utils (top-level)
|
||||
missing module named numpy.core.array_repr - imported by numpy.core (top-level), numpy.testing._private.utils (top-level)
|
||||
missing module named numpy.core.arange - imported by numpy.core (top-level), numpy.testing._private.utils (top-level), numpy.fft.helper (top-level)
|
||||
missing module named numpy.core.empty - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (top-level), numpy.fft.helper (top-level)
|
||||
missing module named numpy.core.float32 - imported by numpy.core (top-level), numpy.testing._private.utils (top-level)
|
||||
missing module named numpy.core.intp - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (top-level)
|
||||
missing module named numpy.core.linspace - imported by numpy.core (top-level), numpy.lib.index_tricks (top-level)
|
||||
missing module named numpy.core.iinfo - imported by numpy.core (top-level), numpy.lib.twodim_base (top-level)
|
||||
missing module named numpy.core.transpose - imported by numpy.core (top-level), numpy.lib.function_base (top-level)
|
||||
missing module named numpy.core.asarray - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.lib.utils (top-level), numpy.fft._pocketfft (top-level), numpy.fft.helper (top-level)
|
||||
missing module named numpy.core.integer - imported by numpy.core (top-level), numpy.fft.helper (top-level)
|
||||
missing module named numpy.core.sqrt - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.fft._pocketfft (top-level)
|
||||
missing module named numpy.core.conjugate - imported by numpy.core (top-level), numpy.fft._pocketfft (top-level)
|
||||
missing module named numpy.core.swapaxes - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.fft._pocketfft (top-level)
|
||||
missing module named numpy.core.zeros - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.fft._pocketfft (top-level)
|
||||
missing module named numpy.core.reciprocal - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.sort - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.argsort - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.sign - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.count_nonzero - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.divide - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.matmul - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.asanyarray - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.atleast_2d - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.product - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.amax - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.amin - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.moveaxis - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.geterrobj - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.finfo - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.lib.polynomial (top-level)
|
||||
missing module named numpy.core.sum - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.multiply - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.add - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.dot - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.lib.polynomial (top-level)
|
||||
missing module named numpy.core.Inf - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.newaxis - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.complexfloating - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.inexact - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.cdouble - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.csingle - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.double - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.single - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.intc - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named numpy.core.empty_like - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
|
||||
missing module named threadpoolctl - imported by numpy.lib.utils (delayed, optional)
|
||||
missing module named numpy.core.ufunc - imported by numpy.core (top-level), numpy.lib.utils (top-level)
|
||||
missing module named numpy.core.ones - imported by numpy.core (top-level), numpy.lib.polynomial (top-level)
|
||||
missing module named numpy.core.hstack - imported by numpy.core (top-level), numpy.lib.polynomial (top-level)
|
||||
missing module named numpy.core.atleast_1d - imported by numpy.core (top-level), numpy.lib.polynomial (top-level)
|
||||
missing module named numpy.core.atleast_3d - imported by numpy.core (top-level), numpy.lib.shape_base (top-level)
|
||||
missing module named numpy.core.vstack - imported by numpy.core (top-level), numpy.lib.shape_base (top-level)
|
||||
missing module named pickle5 - imported by numpy.compat.py3k (optional)
|
||||
missing module named numpy.eye - imported by numpy (delayed), numpy.core.numeric (delayed)
|
||||
missing module named numpy.recarray - imported by numpy (top-level), numpy.ma.mrecords (top-level)
|
||||
missing module named numpy.expand_dims - imported by numpy (top-level), numpy.ma.core (top-level)
|
||||
missing module named numpy.array - imported by numpy (top-level), numpy.ma.core (top-level), numpy.ma.extras (top-level), numpy.ma.mrecords (top-level)
|
||||
missing module named numpy.iscomplexobj - imported by numpy (top-level), numpy.ma.core (top-level)
|
||||
missing module named numpy.amin - imported by numpy (top-level), numpy.ma.core (top-level)
|
||||
missing module named numpy.amax - imported by numpy (top-level), numpy.ma.core (top-level)
|
||||
missing module named numpy.float64 - imported by numpy (top-level), numpy.array_api._typing (top-level)
|
||||
missing module named numpy.float32 - imported by numpy (top-level), numpy.array_api._typing (top-level)
|
||||
missing module named numpy.uint64 - imported by numpy (top-level), numpy.array_api._typing (top-level)
|
||||
missing module named numpy.uint32 - imported by numpy (top-level), numpy.array_api._typing (top-level)
|
||||
missing module named numpy.uint16 - imported by numpy (top-level), numpy.array_api._typing (top-level)
|
||||
missing module named numpy.uint8 - imported by numpy (top-level), numpy.array_api._typing (top-level)
|
||||
missing module named numpy.int64 - imported by numpy (top-level), numpy.array_api._typing (top-level)
|
||||
missing module named numpy.int32 - imported by numpy (top-level), numpy.array_api._typing (top-level)
|
||||
missing module named numpy.int16 - imported by numpy (top-level), numpy.array_api._typing (top-level)
|
||||
missing module named numpy.int8 - imported by numpy (top-level), numpy.array_api._typing (top-level)
|
||||
missing module named _ufunc - imported by numpy._typing (conditional)
|
||||
missing module named numpy.bytes_ - imported by numpy (top-level), numpy._typing._array_like (top-level)
|
||||
missing module named numpy.str_ - imported by numpy (top-level), numpy._typing._array_like (top-level)
|
||||
missing module named numpy.void - imported by numpy (top-level), numpy._typing._array_like (top-level)
|
||||
missing module named numpy.object_ - imported by numpy (top-level), numpy._typing._array_like (top-level)
|
||||
missing module named numpy.datetime64 - imported by numpy (top-level), numpy._typing._array_like (top-level)
|
||||
missing module named numpy.timedelta64 - imported by numpy (top-level), numpy._typing._array_like (top-level)
|
||||
missing module named numpy.number - imported by numpy (top-level), numpy._typing._array_like (top-level)
|
||||
missing module named numpy.complexfloating - imported by numpy (top-level), numpy._typing._array_like (top-level)
|
||||
missing module named numpy.floating - imported by numpy (top-level), numpy._typing._array_like (top-level)
|
||||
missing module named numpy.integer - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.ctypeslib (top-level)
|
||||
missing module named numpy.unsignedinteger - imported by numpy (top-level), numpy._typing._array_like (top-level)
|
||||
missing module named numpy.bool_ - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.ma.core (top-level), numpy.ma.mrecords (top-level)
|
||||
missing module named numpy.generic - imported by numpy (top-level), numpy._typing._array_like (top-level)
|
||||
missing module named numpy.dtype - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.array_api._typing (top-level), numpy.ma.mrecords (top-level), numpy.ctypeslib (top-level)
|
||||
missing module named numpy.ndarray - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.ma.core (top-level), numpy.ma.extras (top-level), numpy.ma.mrecords (top-level), numpy.ctypeslib (top-level)
|
||||
missing module named numpy.ufunc - imported by numpy (top-level), numpy._typing (top-level)
|
||||
missing module named numpy.histogramdd - imported by numpy (delayed), numpy.lib.twodim_base (delayed)
|
||||
missing module named dummy_thread - imported by cffi.lock (conditional, optional)
|
||||
missing module named thread - imported by cffi.lock (conditional, optional), cffi.cparser (conditional, optional)
|
||||
missing module named cStringIO - imported by cPickle (top-level), cffi.ffiplatform (optional)
|
||||
missing module named copy_reg - imported by cPickle (top-level), cStringIO (top-level)
|
||||
missing module named cPickle - imported by pycparser.ply.yacc (delayed, optional)
|
||||
missing module named cffi._pycparser - imported by cffi (optional), cffi.cparser (optional)
|
||||
missing module named 'defusedxml.ElementTree' - imported by openpyxl.xml.functions (conditional), PIL.Image (optional)
|
||||
missing module named Image - imported by docutils.parsers.rst.directives.images (optional)
|
||||
missing module named roman - imported by docutils.writers.latex2e (optional), docutils.writers.manpage (optional)
|
||||
missing module named multiprocessing.set_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
||||
missing module named multiprocessing.get_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
||||
missing module named multiprocessing.get_context - imported by multiprocessing (top-level), multiprocessing.pool (top-level), multiprocessing.managers (top-level), multiprocessing.sharedctypes (top-level)
|
||||
missing module named multiprocessing.TimeoutError - imported by multiprocessing (top-level), multiprocessing.pool (top-level)
|
||||
missing module named multiprocessing.BufferTooShort - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
||||
missing module named multiprocessing.AuthenticationError - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
||||
missing module named 'setuptools.extern.jaraco' - imported by setuptools._reqs (top-level), setuptools._entry_points (top-level), setuptools.command.egg_info (top-level), setuptools._vendor.jaraco.text (top-level)
|
||||
missing module named setuptools.extern.importlib_resources - imported by setuptools.extern (conditional), setuptools._importlib (conditional), setuptools._vendor.jaraco.text (optional)
|
||||
missing module named setuptools.extern.tomli - imported by setuptools.extern (delayed), setuptools.config.pyprojecttoml (delayed)
|
||||
missing module named setuptools.extern.importlib_metadata - imported by setuptools.extern (conditional), setuptools._importlib (conditional)
|
||||
missing module named setuptools.extern.ordered_set - imported by setuptools.extern (top-level), setuptools.dist (top-level)
|
||||
missing module named setuptools.extern.packaging - imported by setuptools.extern (top-level), setuptools.dist (top-level), setuptools.command.egg_info (top-level), setuptools.depends (top-level)
|
||||
missing module named 'setuptools.extern.more_itertools' - imported by setuptools.dist (top-level), setuptools.config.expand (delayed), setuptools.config.pyprojecttoml (delayed), setuptools._itertools (top-level), setuptools._entry_points (top-level), setuptools.msvc (top-level), setuptools._vendor.jaraco.functools (top-level)
|
||||
missing module named 'setuptools.extern.packaging.utils' - imported by setuptools.wheel (top-level)
|
||||
missing module named 'setuptools.extern.packaging.tags' - imported by setuptools.wheel (top-level)
|
||||
missing module named trove_classifiers - imported by setuptools.config._validate_pyproject.formats (optional)
|
||||
missing module named 'setuptools.extern.packaging.specifiers' - imported by setuptools.config.setupcfg (top-level), setuptools.config._apply_pyprojecttoml (delayed)
|
||||
missing module named 'setuptools.extern.packaging.version' - imported by setuptools.config.setupcfg (top-level)
|
||||
missing module named 'setuptools.extern.packaging.markers' - imported by setuptools.config.setupcfg (top-level)
|
||||
missing module named 'setuptools.extern.packaging.requirements' - imported by setuptools.config.setupcfg (top-level)
|
||||
missing module named pyimod02_importers - imported by /Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py (top-level), /Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgres.py (top-level)
|
||||
missing module named _overlapped - imported by asyncio.windows_events (top-level)
|
||||
missing module named asyncio.DefaultEventLoopPolicy - imported by asyncio (delayed, conditional), asyncio.events (delayed, conditional)
|
||||
missing module named htmlentitydefs - imported by lxml.html.soupparser (optional)
|
||||
missing module named BeautifulSoup - imported by lxml.html.soupparser (optional)
|
||||
missing module named bs4.builder.HTMLParserTreeBuilder - imported by bs4.builder (top-level), bs4 (top-level)
|
||||
missing module named 'html5lib.treebuilders' - imported by bs4.builder._html5lib (optional), lxml.html._html5builder (top-level), lxml.html.html5parser (top-level)
|
||||
missing module named 'html5lib.constants' - imported by bs4.builder._html5lib (top-level)
|
||||
missing module named html5lib - imported by bs4.builder._html5lib (top-level), lxml.html.html5parser (top-level)
|
||||
missing module named urlparse - imported by lxml.ElementInclude (optional), lxml.html (optional), lxml.html.html5parser (optional)
|
||||
missing module named urllib2 - imported by lxml.ElementInclude (optional), lxml.html.html5parser (optional)
|
||||
missing module named cssselect - imported by lxml.cssselect (optional)
|
||||
missing module named tests.KEEP_VBA - imported by tests (optional), openpyxl.reader.excel (optional)
|
||||
missing module named defusedxml - imported by openpyxl.xml (delayed, optional)
|
50707
dataloader/macos/build/dataloader/xref-dataloader.html
Normal file
50707
dataloader/macos/build/dataloader/xref-dataloader.html
Normal file
File diff suppressed because it is too large
Load Diff
47
dataloader/macos/dataloader.spec
Executable file
47
dataloader/macos/dataloader.spec
Executable file
@ -0,0 +1,47 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['../dataloader.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[
|
||||
"aiopg",
|
||||
"aiomysql"
|
||||
],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False,
|
||||
)
|
||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name='dataloader',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
BIN
dataloader/macos/dist/dataloader
vendored
Executable file
BIN
dataloader/macos/dist/dataloader
vendored
Executable file
Binary file not shown.
24
dataloader/t.py
Normal file
24
dataloader/t.py
Normal file
@ -0,0 +1,24 @@
|
||||
from appPublic.jsonConfig import getConfig
|
||||
import openpyxl as xlsx
|
||||
import asyncio
|
||||
from sqlor.dbpools import DBPools
|
||||
import aiomysql
|
||||
import aiopg
|
||||
from typeconv import convrec
|
||||
|
||||
async def test():
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
recs = await sor.R('appcodes', {})
|
||||
a = recs[0]['create_at']
|
||||
print('a=', a, type(a), dir(a), '%020d' % int(a.timestamp()*1000))
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
import os
|
||||
p = os.getcwd()
|
||||
config = getConfig(p)
|
||||
print(f'{config.databases=},cwd={p}')
|
||||
db = DBPools(config.databases)
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(test())
|
BIN
dataloader/table1.png
Executable file
BIN
dataloader/table1.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 181 KiB |
BIN
dataloader/table2.png
Executable file
BIN
dataloader/table2.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 200 KiB |
25
dataloader/typeconv.py
Executable file
25
dataloader/typeconv.py
Executable file
@ -0,0 +1,25 @@
|
||||
convfuncs = {
|
||||
'int':int,
|
||||
'long':int,
|
||||
'llong':int,
|
||||
'float':float,
|
||||
'double':float,
|
||||
'date':str,
|
||||
'datetime':str,
|
||||
'ddouble':float
|
||||
}
|
||||
|
||||
def conv(info, name, value):
|
||||
fields = info['fields']
|
||||
for f in fields:
|
||||
if f['name'] == name:
|
||||
f = convfuncs.get(f['type'], None)
|
||||
if f is None or value is None:
|
||||
return value
|
||||
return f(value)
|
||||
return value
|
||||
|
||||
def convrec(info, ns):
|
||||
ret = {k:conv(info, k, v) for k,v in ns.items()}
|
||||
return ret
|
||||
|
4
dataloader/ubuntu/build.sh
Executable file
4
dataloader/ubuntu/build.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
pyinstaller -y --clean dataloader.spec
|
||||
echo "build success, please find the target in dist folder"
|
47
dataloader/ubuntu/dataloader.spec
Executable file
47
dataloader/ubuntu/dataloader.spec
Executable file
@ -0,0 +1,47 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['../dataloader.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[
|
||||
"aiopg",
|
||||
"aiomysql"
|
||||
],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False,
|
||||
)
|
||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name='dataloader',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
2
dataloader/windows/build.bat
Executable file
2
dataloader/windows/build.bat
Executable file
@ -0,0 +1,2 @@
|
||||
pyinstaller -y --clean dataloader.spec
|
||||
echo "build success, please find the target in dist folder"
|
47
dataloader/windows/dataloader.spec
Executable file
47
dataloader/windows/dataloader.spec
Executable file
@ -0,0 +1,47 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['../dataloader.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[
|
||||
"aiopg",
|
||||
"aiomysql"
|
||||
],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False,
|
||||
)
|
||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name='dataloader',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
20
docs/postgresql.md
Executable file
20
docs/postgresql.md
Executable file
@ -0,0 +1,20 @@
|
||||
# POSTGRESQL
|
||||
|
||||
## create database
|
||||
create database testdb;
|
||||
|
||||
## create user
|
||||
|
||||
create role guest with login;
|
||||
|
||||
## grat privileges
|
||||
|
||||
grant all privileges on database testdb to guest;
|
||||
|
||||
### grant table privileges
|
||||
|
||||
psql -d testdb
|
||||
|
||||
grant all privileges on all tables in schema public to guest;
|
||||
|
||||
|
5
requirements.txt
Executable file
5
requirements.txt
Executable file
@ -0,0 +1,5 @@
|
||||
aiomysql
|
||||
PyMySQL
|
||||
aiosqlite
|
||||
asyncio
|
||||
jinja2
|
48
setup.py
Executable file
48
setup.py
Executable file
@ -0,0 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from distutils.core import setup
|
||||
try:
|
||||
from setuptools import setup, find_packages
|
||||
except:
|
||||
from distutils.core import setup
|
||||
|
||||
from sqlor.version import __version__
|
||||
|
||||
version = __version__
|
||||
name = "sqlor"
|
||||
description = "sqlor"
|
||||
author = "yumoqing"
|
||||
email = "yumoqing@gmail.com"
|
||||
|
||||
packages=find_packages()
|
||||
package_data = {}
|
||||
required = []
|
||||
with open('requirements.txt', 'r') as f:
|
||||
ls = f.read()
|
||||
required = ls.split('\n')
|
||||
|
||||
|
||||
with open("README.md", "r") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
setup(
|
||||
name=name,
|
||||
description = description,
|
||||
version=version,
|
||||
author=author,
|
||||
author_email=email,
|
||||
install_requires=required,
|
||||
packages=packages,
|
||||
package_data=package_data,
|
||||
keywords = [
|
||||
],
|
||||
url="https://github.com/yumoqing/sqlor",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
classifiers = [
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python :: 3',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
],
|
||||
)
|
145
sqlor.egg-info/PKG-INFO
Normal file
145
sqlor.egg-info/PKG-INFO
Normal file
@ -0,0 +1,145 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: sqlor
|
||||
Version: 0.1.3
|
||||
Summary: sqlor
|
||||
Home-page: https://github.com/yumoqing/sqlor
|
||||
Author: yumoqing
|
||||
Author-email: yumoqing@gmail.com
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Description-Content-Type: text/markdown
|
||||
|
||||
# SQLOR
|
||||
|
||||
SQLOR is a database api for python3, it is base on the python's DBAPI2
|
||||
|
||||
## Features
|
||||
|
||||
* Multiple database supported(Oracle, MySql, Postgresql, SQL Server
|
||||
* Both asynchronous API & synchronous API supported
|
||||
* Connection pools
|
||||
* Connection life cycle managements
|
||||
* Easy using API
|
||||
* Resources(connection object, cursor object) automatic recycled
|
||||
|
||||
|
||||
## requirements
|
||||
|
||||
* python 3.5 or above
|
||||
* asyncio
|
||||
* Oracle DBAPI2 driver(cx_Oracle)
|
||||
* MySQL DBAPI2 driver(mysql-connector)
|
||||
* Postgresql DBAPI2 driver(psycopg2-binrary)
|
||||
* Asynchronous MySQL driver(aiomysql)
|
||||
* Asynchronous Postgresql driver(aiopg)
|
||||
* Other driver can be easy integreated
|
||||
|
||||
## Using
|
||||
|
||||
```
|
||||
import asyncio
|
||||
|
||||
from sqlor.dbpools import DBPools
|
||||
|
||||
dbs={
|
||||
"aiocfae":{
|
||||
"driver":"aiomysql",
|
||||
"async_mode":True,
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"stock":{
|
||||
"driver":"aiopg",
|
||||
"async_mode":True,
|
||||
"codeing":"utf-8",
|
||||
"dbname":"stock",
|
||||
"kwargs":{
|
||||
"dbname":"stock",
|
||||
"user":"test",
|
||||
"password":"test123",
|
||||
"host":"127.0.0.1"
|
||||
}
|
||||
},
|
||||
"cfae":{
|
||||
"driver":"mysql.connector",
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
pool = DBPools(dbs,loop=loop)
|
||||
|
||||
async def testfunc():
|
||||
@pool.runSQL
|
||||
def sql(db,ns,callback):
|
||||
return {
|
||||
"sql_string":"select * from product",
|
||||
}
|
||||
x = await sql('cfae',{},print)
|
||||
x = await sql('aiocfae',{},print)
|
||||
|
||||
loop.run_until_complete(testfunc())
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
|
||||
### Databases description data(dbdesc)
|
||||
|
||||
sqlor uses a dbdesc data(databases description data) which description
|
||||
how many databases and what database will using, and them connection parameters to create a dbpools objects
|
||||
|
||||
dbdesc data is a dict data, format of the dbdesc as follow:
|
||||
```
|
||||
{
|
||||
"aiocfae":{ # name to identify a database connect
|
||||
"driver":"aiomysql", # database dbapi2 driver package name
|
||||
"async_mode":True, # indicte this connection is asynchronous mode
|
||||
"coding":"utf8", # charset coding
|
||||
"dbname":"cfae", # database real name
|
||||
"kwargs":{ # connection parameters
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"cfae":{
|
||||
"driver":"mysql.connector",
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
sqlor can using multiple databases and difference databases by using difference database driver
|
||||
|
||||
### sql description data
|
||||
|
||||
|
||||
## class
|
||||
|
||||
### DBPools
|
||||
|
||||
### SQLor
|
||||
|
30
sqlor.egg-info/SOURCES.txt
Executable file
30
sqlor.egg-info/SOURCES.txt
Executable file
@ -0,0 +1,30 @@
|
||||
README.md
|
||||
setup.py
|
||||
sqlor/__init__.py
|
||||
sqlor/aiomysqlor.py
|
||||
sqlor/aiopostgresqlor.py
|
||||
sqlor/aiosqliteor.py
|
||||
sqlor/const.py
|
||||
sqlor/crud.py
|
||||
sqlor/dbpools.py
|
||||
sqlor/ddl_template_mysql.py
|
||||
sqlor/ddl_template_oracle.py
|
||||
sqlor/ddl_template_postgresql.py
|
||||
sqlor/ddl_template_sqlite3.py
|
||||
sqlor/ddl_template_sqlserver.py
|
||||
sqlor/filter.py
|
||||
sqlor/mssqlor.py
|
||||
sqlor/mysqlor.py
|
||||
sqlor/oracleor.py
|
||||
sqlor/postgresqlor.py
|
||||
sqlor/records.py
|
||||
sqlor/runsql.py
|
||||
sqlor/sor.py
|
||||
sqlor/sqlite3or.py
|
||||
sqlor/version.py
|
||||
sqlor.egg-info/PKG-INFO
|
||||
sqlor.egg-info/SOURCES.txt
|
||||
sqlor.egg-info/dependency_links.txt
|
||||
sqlor.egg-info/requires.txt
|
||||
sqlor.egg-info/top_level.txt
|
||||
test/test.py
|
1
sqlor.egg-info/dependency_links.txt
Executable file
1
sqlor.egg-info/dependency_links.txt
Executable file
@ -0,0 +1 @@
|
||||
|
5
sqlor.egg-info/requires.txt
Normal file
5
sqlor.egg-info/requires.txt
Normal file
@ -0,0 +1,5 @@
|
||||
aiomysql
|
||||
PyMySQL
|
||||
aiosqlite
|
||||
asyncio
|
||||
jinja2
|
1
sqlor.egg-info/top_level.txt
Executable file
1
sqlor.egg-info/top_level.txt
Executable file
@ -0,0 +1 @@
|
||||
sqlor
|
0
sqlor/__init__.py
Executable file
0
sqlor/__init__.py
Executable file
BIN
sqlor/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
sqlor/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
sqlor/__pycache__/version.cpython-312.pyc
Normal file
BIN
sqlor/__pycache__/version.cpython-312.pyc
Normal file
Binary file not shown.
7
sqlor/aiomysqlor.py
Executable file
7
sqlor/aiomysqlor.py
Executable file
@ -0,0 +1,7 @@
|
||||
from .mysqlor import MySqlor
|
||||
|
||||
class AioMysqlor(MySqlor):
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='aiomysql'
|
||||
|
10
sqlor/aiopostgresqlor.py
Executable file
10
sqlor/aiopostgresqlor.py
Executable file
@ -0,0 +1,10 @@
|
||||
|
||||
from .postgresqlor import PostgreSQLor
|
||||
class AioPostgresqlor(PostgreSQLor):
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='aiopg'
|
||||
|
||||
async def commit(self):
|
||||
pass
|
||||
|
7
sqlor/aiosqliteor.py
Executable file
7
sqlor/aiosqliteor.py
Executable file
@ -0,0 +1,7 @@
|
||||
import re
|
||||
from .sqlite3or import SQLite3or
|
||||
|
||||
class Aiosqliteor(SQLite3or):
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='aiosqlite'
|
1
sqlor/const.py
Executable file
1
sqlor/const.py
Executable file
@ -0,0 +1 @@
|
||||
ROWS=100
|
373
sqlor/crud.py
Executable file
373
sqlor/crud.py
Executable file
@ -0,0 +1,373 @@
|
||||
# -*- coding:utf8 -*-
|
||||
from .dbpools import DBPools
|
||||
from .const import ROWS
|
||||
from .filter import DBFilter
|
||||
from appPublic.objectAction import ObjectAction
|
||||
from appPublic.dictObject import DictObject
|
||||
from appPublic.timeUtils import date2str,time2str,str2Date
|
||||
from appPublic.uniqueID import getID
|
||||
toStringFuncs={
|
||||
'char':None,
|
||||
'str':None,
|
||||
'short':str,
|
||||
'long':str,
|
||||
'float':str,
|
||||
'date':date2str,
|
||||
'time':time2str,
|
||||
}
|
||||
fromStringFuncs={
|
||||
'short':int,
|
||||
'long':int,
|
||||
'float':float,
|
||||
'date':str2Date,
|
||||
'time':str2Date
|
||||
}
|
||||
|
||||
class DatabaseNotfound(Exception):
|
||||
def __init__(self,dbname):
|
||||
Exception.__init__(self)
|
||||
self.dbname = dbname
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.dbname} not found'
|
||||
|
||||
class CRUD(object):
|
||||
def __init__(self,dbname,tablename,rows=ROWS):
|
||||
self.pool = DBPools()
|
||||
if dbname not in self.pool.databases.keys():
|
||||
raise DatabaseNotfound(dbname)
|
||||
self.dbname = dbname
|
||||
self.tablename = tablename
|
||||
self.rows = rows
|
||||
self.primary_data = None
|
||||
self.oa = ObjectAction()
|
||||
|
||||
async def primaryKey(self,**kw):
|
||||
if self.primary_data is None:
|
||||
self.primary_data = await self.pool.getTablePrimaryKey(self.dbname,
|
||||
self.tablename,**kw)
|
||||
|
||||
return self.primary_data
|
||||
|
||||
async def forignKeys(self,**kw):
|
||||
data = self.pool.getTableForignKeys(self.dbname,self.tablename,**kw)
|
||||
return data
|
||||
|
||||
async def I(self,**kw):
|
||||
"""
|
||||
fields information
|
||||
"""
|
||||
@self.pool.inSqlor
|
||||
async def main(dbname,NS,**kw):
|
||||
pkdata = await self.primaryKey(**kw)
|
||||
pks = [ i.field_name for i in pkdata ]
|
||||
data = await self.pool.getTableFields(self.dbname,self.tablename,**kw)
|
||||
for d in data:
|
||||
if d.name in pks:
|
||||
d.update({'primarykey':True})
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'tableInfo',data)
|
||||
return data
|
||||
|
||||
return await main(self.dbname,{},**kw)
|
||||
|
||||
async def fromStr(self,data):
|
||||
fields = await self.pool.getTableFields(self.dbname,self.tablename)
|
||||
ret = {}
|
||||
for k in data:
|
||||
v = None if data[k] == '' else data[k]
|
||||
for f in fields:
|
||||
if k == f.name:
|
||||
ret[k] = v
|
||||
f = fromStringFuncs.get(f.type,None)
|
||||
if f is not None and v is not None:
|
||||
ret[k] = f(v)
|
||||
return ret
|
||||
|
||||
async def toStr(self,data):
|
||||
fields = await self.pool.getTableFields(self.dbname,self.tablename)
|
||||
ret = {}
|
||||
for k in data:
|
||||
for f in fields:
|
||||
if k == f.name:
|
||||
ret[k] = data[k]
|
||||
f = toStringFuncs.get(f.type,None)
|
||||
if f is not None and data[k] is not None:
|
||||
ret[k] = f(data[k])
|
||||
return ret
|
||||
|
||||
async def datagrid(self,request,targeti,**kw):
|
||||
fields = await self.I()
|
||||
fs = [ self.defaultIOField(f) for f in fields ]
|
||||
id = self.dbname+':'+ self.tablename
|
||||
pk = await self.primaryKey(**kw)
|
||||
idField = pk[0]['field_name']
|
||||
data = {
|
||||
"tmplname":"widget_js.tmpl",
|
||||
"data":{
|
||||
"__ctmpl__":"datagrid",
|
||||
"__target__":target,
|
||||
"data":{
|
||||
"name":id,
|
||||
"icon-conv":"icon-table",
|
||||
"title":tablename,
|
||||
"url":absurl('./RP.dspy?id=%s' % id),
|
||||
"deleteUrl":absurl('./D.dspy?id=%s' % id),
|
||||
"addUrl":absurl('./C.dspy?id=%s' % id),
|
||||
"updateUrl":absurl('./U.dspy?id=%s' % id),
|
||||
"idField":idField,
|
||||
"dnd":True,
|
||||
"view":"scrollview",
|
||||
"fields":fs,
|
||||
"toolbar":{
|
||||
"tools":[
|
||||
{
|
||||
"name":"add",
|
||||
"icon":"icon-add",
|
||||
"label":"add ball"
|
||||
},
|
||||
{
|
||||
"name":"delete",
|
||||
"icon":"icon-delete",
|
||||
"label":"delete ball"
|
||||
},
|
||||
{
|
||||
"name":"moveup",
|
||||
"icon":"icon-up",
|
||||
"label":"moveup ball"
|
||||
},
|
||||
{
|
||||
"name":"movedown",
|
||||
"icon":"icon-down",
|
||||
"label":"movedown ball"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options":{
|
||||
"pageSize":50,
|
||||
"pagination":False
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data = self.oa.execute(id,'datagrid',data)
|
||||
return data
|
||||
|
||||
def defaultIOField(self,f):
|
||||
if f.type in ['str']:
|
||||
return {
|
||||
"primarykey":f.get('primarykey',False),
|
||||
"name":f.name,
|
||||
"hidden":False,
|
||||
"sortable":True,
|
||||
"label":f.title,
|
||||
"align":"center",
|
||||
"iotype":"text"
|
||||
}
|
||||
if f.type in ['float','short','long']:
|
||||
return {
|
||||
"primarykey":f.get('primarykey',False),
|
||||
"sortable":True,
|
||||
"name":f.name,
|
||||
"hidden":False,
|
||||
"label":f.title,
|
||||
"align":"right",
|
||||
"iotype":"text"
|
||||
}
|
||||
return {
|
||||
"primarykey":f.get('primarykey',False),
|
||||
"name":f.name,
|
||||
"sortable":True,
|
||||
"hidden":False,
|
||||
"label":f.title,
|
||||
"align":"center",
|
||||
"iotype":"text"
|
||||
}
|
||||
|
||||
async def C(self,rec,**kw):
|
||||
"""
|
||||
create new data
|
||||
"""
|
||||
@self.pool.runSQL
|
||||
async def addSQL(dbname,data,**kw):
|
||||
fns = kw['fns']
|
||||
vfs = kw['vfs']
|
||||
sqldesc={
|
||||
"sql_string" : """
|
||||
insert into %s (%s) values (%s)
|
||||
""" % (self.tablename,fns,vfs),
|
||||
}
|
||||
return sqldesc
|
||||
|
||||
@self.pool.inSqlor
|
||||
async def main(dbname,NS,**kw):
|
||||
fields = await self.pool.getTableFields(self.dbname,self.tablename,**kw)
|
||||
flist = [ f['name'] for f in fields ]
|
||||
fns = ','.join(flist)
|
||||
vfs = ','.join([ '${' + f + '}$' for f in flist ])
|
||||
data = {}
|
||||
[ data.update({k.lower():v}) for k,v in NS.items() ]
|
||||
pk = await self.primaryKey(**kw)
|
||||
k = pk[0]['field_name']
|
||||
if not data.get(k):
|
||||
v = getID()
|
||||
data[k] = v
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'beforeAdd',data)
|
||||
kwargs = kw.copy()
|
||||
kwargs['fns'] = fns
|
||||
kwargs['vfs'] = vfs
|
||||
await addSQL(self.dbname,data,**kwargs)
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'afterAdd',data)
|
||||
return {k:data[k]}
|
||||
|
||||
return await main(self.dbname,rec,**kw)
|
||||
|
||||
async def defaultFilter(self,NS,**kw):
|
||||
fields = await self.pool.getTableFields(self.dbname,self.tablename,**kw)
|
||||
d = [ '%s = ${%s}$' % (f['name'],f['name']) for f in fields if f['name'] in NS.keys() ]
|
||||
if len(d) == 0:
|
||||
return ''
|
||||
ret = ' and ' + ' and '.join(d)
|
||||
return ret
|
||||
|
||||
async def R(self,filters=None,NS={},**kw):
|
||||
"""
|
||||
retrieve data
|
||||
"""
|
||||
@self.pool.runSQL
|
||||
async def retrieve(dbname,data,**kw):
|
||||
fstr = ''
|
||||
if filters is not None:
|
||||
fstr = ' and '
|
||||
dbf = DBFilter(filters)
|
||||
fstr = fstr + dbf.genFilterString()
|
||||
else:
|
||||
fstr = await self.defaultFilter(NS,**kw)
|
||||
sqldesc = {
|
||||
"sql_string":"""select * from %s where 1=1 %s""" % (self.tablename,fstr),
|
||||
}
|
||||
return sqldesc
|
||||
|
||||
@self.pool.runSQLPaging
|
||||
async def pagingdata(dbname,data,filters=None,**kw):
|
||||
fstr = ""
|
||||
if filters is not None:
|
||||
fstr = ' and '
|
||||
dbf = DBFilter(filters)
|
||||
fstr = fstr + dbf.genFilterString()
|
||||
else:
|
||||
fstr = await self.defaultFilter(NS,**kw)
|
||||
|
||||
sqldesc = {
|
||||
"sql_string":"""select * from %s where 1=1 %s""" % (self.tablename,fstr),
|
||||
"default":{'rows':self.rows}
|
||||
}
|
||||
return sqldesc
|
||||
|
||||
@self.pool.inSqlor
|
||||
async def main(dbname,NS,**kw):
|
||||
p = await self.primaryKey(**kw)
|
||||
if NS.get('__id') is not None:
|
||||
NS[p[0]['field_name']] = NS['__id']
|
||||
del NS['__id']
|
||||
if NS.get('page'):
|
||||
del NS['page']
|
||||
|
||||
if NS.get('page'):
|
||||
if NS.get('sort',None) is None:
|
||||
NS['sort'] = p[0]['field_name']
|
||||
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'beforeRetrieve',NS)
|
||||
if NS.get('page'):
|
||||
data = await pagingdata(self.dbname,data,**kw)
|
||||
else:
|
||||
data = await retrieve(self.dbname,data,**kw)
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'afterRetrieve',data)
|
||||
return data
|
||||
|
||||
return await main(self.dbname,NS,**kw)
|
||||
|
||||
async def U(self,data, **kw):
|
||||
"""
|
||||
update data
|
||||
"""
|
||||
@self.pool.runSQL
|
||||
async def update(dbname,NS,**kw):
|
||||
condi = [ i['field_name'] for i in self.primary_data ]
|
||||
newData = [ i for i in NS.keys() if i not in condi ]
|
||||
c = [ '%s = ${%s}$' % (i,i) for i in condi ]
|
||||
u = [ '%s = ${%s}$' % (i,i) for i in newData ]
|
||||
cs = ' and '.join(c)
|
||||
us = ','.join(u)
|
||||
sqldesc = {
|
||||
"sql_string":"""update %s set %s where %s""" % (self.tablename,us,cs)
|
||||
}
|
||||
return sqldesc
|
||||
|
||||
@self.pool.inSqlor
|
||||
async def main(dbname,NS,**kw):
|
||||
pk = await self.primaryKey(**kw)
|
||||
pkfields = [k.field_name for k in pk ]
|
||||
newData = [ k for k in data if k not in pkfields ]
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'beforeUpdate',data)
|
||||
await update(self.dbname,data,**kw)
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'afterUpdate',data)
|
||||
return data
|
||||
return await main(self.dbname,data,**kw)
|
||||
|
||||
async def D(self,data,**kw):
|
||||
"""
|
||||
delete data
|
||||
"""
|
||||
@self.pool.runSQL
|
||||
def delete(dbname,data,**kw):
|
||||
pnames = [ i['field_name'] for i in self.primary_data ]
|
||||
c = [ '%s = ${%s}$' % (i,i) for i in pnames ]
|
||||
cs = ' and '.join(c)
|
||||
sqldesc = {
|
||||
"sql_string":"delete from %s where %s" % (self.tablename,cs)
|
||||
}
|
||||
return sqldesc
|
||||
|
||||
@self.pool.inSqlor
|
||||
async def main(dbname,NS,**kw):
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'beforeDelete',data)
|
||||
await delete(self.dbname,data,pkfields,**kw)
|
||||
data = self.oa.execute(self.dbname+'_'+self.tablename,'afterDelete',data)
|
||||
return data
|
||||
return await main(self.dbname,data,**kw)
|
||||
|
||||
if __name__ == '__main__':
|
||||
DBPools({
|
||||
"ambi":{
|
||||
"driver":"pymssql",
|
||||
"coding":"utf-8",
|
||||
"dbname":"ambi",
|
||||
"kwargs":{
|
||||
"user":"ymq",
|
||||
"database":"ambi",
|
||||
"password":"ymq123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"metadb":{
|
||||
"driver":"pymssql",
|
||||
"coding":"utf-8",
|
||||
"dbname":"metadb",
|
||||
"kwargs":{
|
||||
"user":"ymq",
|
||||
"database":"metadb",
|
||||
"password":"ymq123",
|
||||
"host":"localhost"
|
||||
}
|
||||
}
|
||||
})
|
||||
crud = CRUD('ambi')
|
||||
#fields = crud.I('cashflow')
|
||||
#for i in fields:
|
||||
# print(i)
|
||||
|
||||
data = crud.RP('cashflow')
|
||||
print(data.total)
|
||||
for i in data.rows:
|
||||
print(i.balance,i.asid)
|
||||
|
493
sqlor/dbpools.py
Executable file
493
sqlor/dbpools.py
Executable file
@ -0,0 +1,493 @@
|
||||
|
||||
import asyncio
|
||||
from traceback import print_exc
|
||||
from functools import wraps
|
||||
import codecs
|
||||
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from appPublic.myImport import myImport
|
||||
from appPublic.dictObject import DictObject
|
||||
from appPublic.Singleton import SingletonDecorator
|
||||
from appPublic.myjson import loadf
|
||||
from appPublic.jsonConfig import getConfig
|
||||
from appPublic.rc4 import unpassword
|
||||
|
||||
import threading
|
||||
from .sor import SQLor
|
||||
from .mssqlor import MsSqlor
|
||||
from .oracleor import Oracleor
|
||||
from .sqlite3or import SQLite3or
|
||||
from .aiosqliteor import Aiosqliteor
|
||||
from .mysqlor import MySqlor
|
||||
from .aiomysqlor import AioMysqlor
|
||||
from .aiopostgresqlor import AioPostgresqlor
|
||||
|
||||
def sqlorFactory(dbdesc):
|
||||
driver = dbdesc.get('driver',dbdesc)
|
||||
def findSubclass(name,klass):
|
||||
for k in klass.__subclasses__():
|
||||
if k.isMe(name):
|
||||
return k
|
||||
k1 = findSubclass(name,k)
|
||||
if k1 is not None:
|
||||
return k1
|
||||
return None
|
||||
k = findSubclass(driver,SQLor)
|
||||
if k is None:
|
||||
return SQLor(dbdesc=dbdesc)
|
||||
return k(dbdesc=dbdesc)
|
||||
|
||||
def sqlorFromFile(dbdef_file,coding='utf8'):
|
||||
dbdef = loadf(dbdef_file)
|
||||
return sqlorFactory(dbdef)
|
||||
|
||||
class LifeConnect:
|
||||
def __init__(self,connfunc,kw,use_max=1000,async_mode=False):
|
||||
self.connfunc = connfunc
|
||||
self.async_mode = async_mode
|
||||
self.use_max = use_max
|
||||
self.kw = kw
|
||||
self.conn = None
|
||||
self.used = False
|
||||
|
||||
def print(self):
|
||||
print(self.use_max)
|
||||
print(self.conn)
|
||||
|
||||
async def _mkconn(self):
|
||||
if self.async_mode:
|
||||
self.conn = await self.connfunc(**self.kw)
|
||||
else:
|
||||
self.conn = self.connfunc(**self.kw)
|
||||
self.use_cnt = 0
|
||||
|
||||
async def use(self):
|
||||
if self.conn is None:
|
||||
await self._mkconn()
|
||||
wait_time = 0.2
|
||||
loop_cnt = 4
|
||||
while loop_cnt > 0:
|
||||
if await self.testok():
|
||||
return self.conn
|
||||
await asyncio.sleep(wait_time)
|
||||
wait_time = wait_time + 0.4
|
||||
loop_cnt = loop_cnt - 1
|
||||
try:
|
||||
await self.conn.close()
|
||||
except:
|
||||
pass
|
||||
self.conn = None
|
||||
await self._mkconn()
|
||||
raise Exception('database connect break')
|
||||
|
||||
async def free(self,conn):
|
||||
self.use_cnt = self.use_cnt + 1
|
||||
return
|
||||
if self.use_cnt >= self.use_max:
|
||||
await self.conn.close()
|
||||
await self._mkcomm()
|
||||
|
||||
async def testok(self):
|
||||
if self.async_mode:
|
||||
async with self.conn.cursor() as cur:
|
||||
try:
|
||||
await cur.execute('select 1 as cnt')
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
else:
|
||||
cur = self.conn.cursor()
|
||||
try:
|
||||
cur.execute('select 1 as cnt')
|
||||
r = cur.fetchall()
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
finally:
|
||||
cur.close()
|
||||
|
||||
class ConnectionPool(object):
|
||||
def __init__(self,dbdesc,loop):
|
||||
self.dbdesc = dbdesc
|
||||
self.async_mode = dbdesc.get('async_mode',False)
|
||||
self.loop = loop
|
||||
self.driver = myImport(self.dbdesc['driver'])
|
||||
self.maxconn = dbdesc.get('maxconn',5)
|
||||
self.maxuse = dbdesc.get('maxuse',1000)
|
||||
self._pool = asyncio.Queue(self.maxconn)
|
||||
self.connectObject = {}
|
||||
self.use_cnt = 0
|
||||
self.max_use = 1000
|
||||
# self.lock = asyncio.Lock()
|
||||
# self.lockstatus()
|
||||
|
||||
def lockstatus(self):
|
||||
return
|
||||
self.loop.call_later(5,self.lockstatus)
|
||||
print('--lock statu=',self.lock.locked(),
|
||||
'--pool empty()=',self._pool.empty(),
|
||||
'--full()=',self._pool.full()
|
||||
)
|
||||
|
||||
async def _fillPool(self):
|
||||
for i in range(self.maxconn):
|
||||
lc = await self.connect()
|
||||
i = i + 1
|
||||
|
||||
async def connect(self):
|
||||
lc = LifeConnect(self.driver.connect,self.dbdesc['kwargs'],
|
||||
use_max=self.maxuse,async_mode=self.async_mode)
|
||||
await self._pool.put(lc)
|
||||
return lc
|
||||
|
||||
def isEmpty(self):
|
||||
return self._pool.empty()
|
||||
|
||||
def isFull(self):
|
||||
return self._pool.full()
|
||||
|
||||
async def aquire(self):
|
||||
lc = await self._pool.get()
|
||||
conn = await lc.use()
|
||||
"""
|
||||
with await self.lock:
|
||||
self.connectObject[lc.conn] = lc
|
||||
"""
|
||||
self.connectObject[lc.conn] = lc
|
||||
return conn
|
||||
|
||||
async def release(self,conn):
|
||||
lc = None
|
||||
"""
|
||||
with await self.lock:
|
||||
lc = self.connectObject.get(conn,None)
|
||||
del self.connectObject[conn]
|
||||
"""
|
||||
lc = self.connectObject.get(conn,None)
|
||||
del self.connectObject[conn]
|
||||
await self._pool.put(lc)
|
||||
|
||||
@SingletonDecorator
|
||||
class DBPools:
|
||||
def __init__(self,databases={},max_connect=100,loop=None):
|
||||
if loop is None:
|
||||
loop = asyncio.get_event_loop()
|
||||
self.loop = loop
|
||||
self.max_connect = max_connect
|
||||
self.sema = asyncio.Semaphore(max_connect)
|
||||
self._cpools = {}
|
||||
self.databases = databases
|
||||
self.meta = {}
|
||||
|
||||
def get_dbname(self, name):
|
||||
desc = self.database.get(name)
|
||||
if not desc:
|
||||
return None
|
||||
return desc.get('dbname')
|
||||
|
||||
def addDatabase(self,name,desc):
|
||||
self.databases[name] = desc
|
||||
|
||||
async def getSqlor(self,name):
|
||||
await self.sema.acquire()
|
||||
desc = self.databases.get(name)
|
||||
sor = sqlorFactory(desc)
|
||||
sor.name = name
|
||||
a,conn,cur = await self._aquireConn(name)
|
||||
sor.setCursor(a,conn,cur)
|
||||
return sor
|
||||
|
||||
async def freeSqlor(self,sor):
|
||||
await self._releaseConn(sor.name,sor.conn,sor.cur)
|
||||
self.sema.release()
|
||||
|
||||
@asynccontextmanager
|
||||
async def sqlorContext(self,name):
|
||||
sqlor = await self.getSqlor(name)
|
||||
try:
|
||||
yield sqlor
|
||||
except Exception as e:
|
||||
print_exc()
|
||||
print('Exeception=',e)
|
||||
if sqlor and sqlor.dataChanged:
|
||||
await sqlor.rollback()
|
||||
finally:
|
||||
if sqlor and sqlor.dataChanged:
|
||||
await sqlor.commit()
|
||||
await self.freeSqlor(sqlor)
|
||||
|
||||
async def _aquireConn(self,dbname):
|
||||
"""
|
||||
p = self._cpools.get(dbname)
|
||||
if p == None:
|
||||
p = ConnectionPool(self.databases.get(dbname),self.loop)
|
||||
await p._fillPool()
|
||||
self._cpools[dbname] = p
|
||||
conn = await p.aquire()
|
||||
if self.isAsyncDriver(dbname):
|
||||
cur = await conn.cursor()
|
||||
else:
|
||||
cur = conn.cursor()
|
||||
return self.isAsyncDriver(dbname),conn,cur
|
||||
"""
|
||||
dbdesc = self.databases.get(dbname)
|
||||
driver = myImport(dbdesc['driver'])
|
||||
conn = None
|
||||
cur = None
|
||||
desc = dbdesc['kwargs'].copy()
|
||||
pw = desc.get('password')
|
||||
if pw:
|
||||
desc['password'] = unpassword(pw)
|
||||
if self.isAsyncDriver(dbname):
|
||||
if dbdesc['driver'] == 'sqlite3':
|
||||
conn = await driver.connect(desc['dbname'])
|
||||
else:
|
||||
conn = await driver.connect(**desc)
|
||||
cur = await conn.cursor()
|
||||
return True,conn,cur
|
||||
else:
|
||||
if dbdesc['driver'] == 'sqlite3':
|
||||
conn = driver.connect(desc['dbname'])
|
||||
else:
|
||||
conn = driver.connect(**desc)
|
||||
cur = conn.cursor()
|
||||
return False,conn,cur
|
||||
|
||||
def isAsyncDriver(self,dbname):
|
||||
ret = self.databases[dbname].get('async_mode',False)
|
||||
return ret
|
||||
|
||||
async def _releaseConn(self,dbname,conn,cur):
|
||||
"""
|
||||
if self.isAsyncDriver(dbname):
|
||||
await cur.close()
|
||||
else:
|
||||
try:
|
||||
cur.fetchall()
|
||||
except:
|
||||
pass
|
||||
cur.close()
|
||||
p = self._cpools.get(dbname)
|
||||
if p == None:
|
||||
raise Exception('database (%s) not connected'%dbname)
|
||||
await p.release(conn)
|
||||
"""
|
||||
if self.isAsyncDriver(dbname):
|
||||
try:
|
||||
await cur.close()
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
cur.fetchall()
|
||||
except:
|
||||
pass
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
async def useOrGetSor(self,dbname,**kw):
|
||||
commit = False
|
||||
if kw.get('sor'):
|
||||
sor = kw['sor']
|
||||
else:
|
||||
sor = await self.getSqlor(dbname)
|
||||
commit = True
|
||||
return sor, commit
|
||||
|
||||
def inSqlor(self,func):
|
||||
@wraps(func)
|
||||
async def wrap_func(dbname,NS,*args,**kw):
|
||||
sor, commit = await self.useOrGetSor(dbname, **kw)
|
||||
kw['sor'] = sor
|
||||
try:
|
||||
ret = await func(dbname,NS,*args,**kw)
|
||||
if not commit:
|
||||
return ret
|
||||
try:
|
||||
await sor.conn.commit()
|
||||
except:
|
||||
pass
|
||||
return ret
|
||||
except Exception as e:
|
||||
print('error',sor)
|
||||
if not commit:
|
||||
raise e
|
||||
try:
|
||||
await sor.conn.rollback()
|
||||
except:
|
||||
pass
|
||||
raise e
|
||||
finally:
|
||||
if commit:
|
||||
await self.freeSqlor(sor)
|
||||
|
||||
return wrap_func
|
||||
|
||||
def runSQL(self,func):
|
||||
@wraps(func)
|
||||
async def wrap_func(dbname,NS,*args,**kw):
|
||||
sor, commit = await self.useOrGetSor(dbname,**kw)
|
||||
kw['sor'] = sor
|
||||
ret = None
|
||||
try:
|
||||
desc = await func(dbname,NS,*args,**kw)
|
||||
callback = kw.get('callback',None)
|
||||
kw1 = {}
|
||||
[ kw1.update({k:v}) for k,v in kw.items() if k!='callback' ]
|
||||
ret = await sor.runSQL(desc,NS,callback,**kw1)
|
||||
if commit:
|
||||
try:
|
||||
await sor.conn.commit()
|
||||
except:
|
||||
pass
|
||||
if NS.get('dummy'):
|
||||
return NS['dummy']
|
||||
else:
|
||||
return []
|
||||
except Exception as e:
|
||||
print('error:',e)
|
||||
if not commit:
|
||||
raise e
|
||||
try:
|
||||
await sor.conn.rollback()
|
||||
except:
|
||||
pass
|
||||
raise e
|
||||
finally:
|
||||
if commit:
|
||||
await self.freeSqlor(sor)
|
||||
return wrap_func
|
||||
|
||||
def runSQLPaging(self,func):
|
||||
@wraps(func)
|
||||
async def wrap_func(dbname,NS,*args,**kw):
|
||||
sor, commit = await self.useOrGetSor(dbname,**kw)
|
||||
kw['sor'] = sor
|
||||
try:
|
||||
desc = await func(dbname,NS,*args,**kw)
|
||||
return await sor.runSQLPaging(desc,NS)
|
||||
except Exception as e:
|
||||
print('error',e)
|
||||
raise e
|
||||
finally:
|
||||
if commit:
|
||||
await self.freeSqlor(sor)
|
||||
return wrap_func
|
||||
|
||||
async def runSQLResultFields(self, func):
|
||||
@wraps(func)
|
||||
async def wrap_func(dbname,NS,*args,**kw):
|
||||
sor, commit = await self.useOrGetSor(dbname,**kw)
|
||||
kw['sor'] = sor
|
||||
try:
|
||||
desc = await func(dbname,NS,*args,**kw)
|
||||
ret = await sor.resultFields(desc,NS)
|
||||
return ret
|
||||
except Exception as e:
|
||||
print('error=',e)
|
||||
raise e
|
||||
finally:
|
||||
if commit:
|
||||
await self.freeSqlor(sor)
|
||||
return wrap_func
|
||||
|
||||
def setMeta(self,key,n,v):
|
||||
if not self.meta.get(key):
|
||||
self.meta[key] = {}
|
||||
self.meta[key][n] = v
|
||||
|
||||
def getMeta(self,key,n=None):
|
||||
if not self.meta.get(key):
|
||||
self.meta[key] = {}
|
||||
|
||||
if n is None:
|
||||
return self.meta[key]
|
||||
return self.meta[key].get(n,None)
|
||||
|
||||
async def getTables(self,dbname,**kw):
|
||||
@self.inSqlor
|
||||
async def _getTables(dbname,NS,**kw):
|
||||
sor = kw['sor']
|
||||
ret = await sor.tables()
|
||||
return ret
|
||||
return await _getTables(dbname,{},**kw)
|
||||
|
||||
async def getTableFields(self,dbname,tblname,**kw):
|
||||
@self.inSqlor
|
||||
async def _getTableFields(dbname,NS,tblname,**kw):
|
||||
key = '%s:%s' % (dbname,tblname)
|
||||
fields = self.getMeta(key, 'fields')
|
||||
if fields:
|
||||
return fields
|
||||
sor = kw['sor']
|
||||
ret = await sor.fields(tblname)
|
||||
self.setMeta(key,'fields',ret)
|
||||
return ret
|
||||
return await _getTableFields(dbname,{},tblname,**kw)
|
||||
|
||||
async def getTablePrimaryKey(self,dbname,tblname,**kw):
|
||||
@self.inSqlor
|
||||
async def _getTablePrimaryKey(dbname,NS,tblname,**kw):
|
||||
key = '%s:%s' % (dbname,tblname)
|
||||
pri = self.getMeta(key,'primarykey')
|
||||
if pri:
|
||||
return pri
|
||||
sor = kw['sor']
|
||||
ret = await sor.primary(tblname)
|
||||
self.setMeta(key,'primarykey',ret)
|
||||
return ret
|
||||
return await _getTablePrimaryKey(dbname,{},tblname,**kw)
|
||||
|
||||
async def getTableIndexes(self,dbname,tblname,**kw):
|
||||
@self.inSqlor
|
||||
async def _getTablePrimaryKey(dbname,NS,tblname,**kw):
|
||||
key = '%s:%s' % (dbname,tblname)
|
||||
idxes = self.getMeta(key,'indexes')
|
||||
if idxes:
|
||||
return idxes
|
||||
sor = kw['sor']
|
||||
ret = await sor.indexes(tblname)
|
||||
self.setMeta(key,'indexes',ret)
|
||||
return ret
|
||||
return await _getTablePrimaryKey(dbname,{},tblname,**kw)
|
||||
|
||||
async def getTableForignKeys(self,dbname,tblname,**kw):
|
||||
@self.inSqlor
|
||||
async def _getTableForignKeys(dbname,NS,tblname,**kw):
|
||||
key = '%s:%s' % (dbname,tblname)
|
||||
forignkeys = self.getMeta(key,'forignkeys')
|
||||
if forignkeys:
|
||||
return forignkeys
|
||||
sor = kw['sor']
|
||||
ret = await sor.fkeys(tblname)
|
||||
self.setMeta(key,'forignkeys',forignkeys)
|
||||
return ret
|
||||
return await _getTableForignKeys(dbname,{},tblname,**kw)
|
||||
|
||||
async def runSQL(dbname,sql,ns={},sor=None):
|
||||
pool = DBPools()
|
||||
@pool.runSQL
|
||||
async def desc(dbname,ns,*args,**kw):
|
||||
return {
|
||||
"sql_string":sql
|
||||
}
|
||||
kw = {
|
||||
'sor':sor
|
||||
}
|
||||
x = await desc(dbname,ns,**kw)
|
||||
return x
|
||||
|
||||
async def runSQLPaging(dbname,sql,ns={},sor=None):
|
||||
pool = DBPools()
|
||||
@pool.runSQLPaging
|
||||
async def desc(dbname,ns,*args,**kw):
|
||||
return {
|
||||
"sql_string":sql
|
||||
}
|
||||
kw = {
|
||||
"sor":sor
|
||||
}
|
||||
x = await desc(dbname, ns, **kw)
|
||||
return x
|
||||
|
58
sqlor/ddl_template_mysql.py
Executable file
58
sqlor/ddl_template_mysql.py
Executable file
@ -0,0 +1,58 @@
|
||||
mysql_ddl_tmpl = """{% macro typeStr(type,len,dec) %}
|
||||
{%- if type=='str' -%}
|
||||
VARCHAR({{len}})
|
||||
{%- elif type=='char' -%}
|
||||
CHAR({{len}})
|
||||
{%- elif type=='long' or type=='int' or type=='short' -%}
|
||||
int
|
||||
{%- elif type=='long' -%}
|
||||
bigint
|
||||
{%- elif type=='float' or type=='double' or type=='ddouble' -%}
|
||||
double({{len}},{{dec}})
|
||||
{%- elif type=='date' -%}
|
||||
date
|
||||
{%- elif type=='time' -%}
|
||||
time
|
||||
{%- elif type=='datetime' -%}
|
||||
datetime
|
||||
{%- elif type=='timestamp' -%}
|
||||
TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
{%- elif type=='text' -%}
|
||||
longtext
|
||||
{%- elif type=='bin' -%}
|
||||
longblob
|
||||
{%- else -%}
|
||||
{{type}}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro defaultValue(defaultv) %}
|
||||
{%- if defaultv %} DEFAULT '{{defaultv}}'{%- endif -%}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro nullStr(nullable) %}
|
||||
{%- if nullable=='no' -%}
|
||||
NOT NULL
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% macro primary() %}
|
||||
,primary key({{','.join(summary[0].primary)}})
|
||||
{% endmacro %}
|
||||
drop table if exists {{summary[0].name}};
|
||||
CREATE TABLE {{summary[0].name}}
|
||||
(
|
||||
{% for field in fields %}
|
||||
`{{field.name}}` {{typeStr(field.type,field.length,field.dec)}} {{nullStr(field.nullable)}} {{defaultValue(field.default)}} {%if field.title -%} comment '{{field.title}}'{%- endif %}{%- if not loop.last -%},{%- endif -%}
|
||||
{% endfor %}
|
||||
{% if summary[0].primary and len(summary[0].primary)>0 %}
|
||||
{{primary()}}
|
||||
{% endif %}
|
||||
)
|
||||
engine=innodb
|
||||
default charset=utf8
|
||||
{% if summary[0].title %}comment '{{summary[0].title}}'{% endif %}
|
||||
;
|
||||
{% for v in indexes %}
|
||||
CREATE {% if v.idxtype=='unique' %}UNIQUE{% endif %} INDEX {{summary[0].name}}_{{v.name}} ON {{summary[0].name}}({{",".join(v.idxfields)}});
|
||||
{%- endfor -%}
|
||||
"""
|
47
sqlor/ddl_template_oracle.py
Executable file
47
sqlor/ddl_template_oracle.py
Executable file
@ -0,0 +1,47 @@
|
||||
oracle_ddl_tmpl = """{% macro typeStr(type,len,dec) %}
|
||||
{%- if type=='str' -%}
|
||||
VARCHAR2({{len}})
|
||||
{%- elif type=='char' -%}
|
||||
CHAR({{len}})
|
||||
{%- elif type=='long' or type=='int' or type=='short' -%}
|
||||
NUMBER
|
||||
{%- elif type=='float' or type=='double' or type=='ddouble' -%}
|
||||
NUMBER({{len}},{{dec}})
|
||||
{%- elif type=='date' or type=='time' -%}
|
||||
DATE
|
||||
{%- elif type=='timestamp' -%}
|
||||
TIMESTAMP
|
||||
{%- elif type=='text' -%}
|
||||
CLOB
|
||||
{%- elif type=='bin' -%}
|
||||
BLOB
|
||||
{%- else -%}
|
||||
{{type}}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
{% macro nullStr(nullable) %}
|
||||
{%- if nullable=='no' -%}
|
||||
NOT NULL
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% macro primary() %}
|
||||
,primary key({{','.join(summary[0].primary)}})
|
||||
{% endmacro %}
|
||||
drop table {{summary[0].name}};
|
||||
CREATE TABLE {{summary[0].name}}
|
||||
(
|
||||
{% for field in fields %}
|
||||
{{field.name}} {{typeStr(field.type,field.length,field.dec)}} {{nullStr(field.nullable)}}{%- if not loop.last -%},{%- endif -%}
|
||||
{% endfor %}
|
||||
{% if summary[0].primary and len(summary[0].primary)>0 %}
|
||||
{{primary()}}
|
||||
{% endif %}
|
||||
);
|
||||
{% for v in indexes %}
|
||||
CREATE {% if v.idxtype=='unique' %}UNIQUE{% endif %} INDEX {{summary[0].name}}_{{v.name}} ON {{summary[0].name}}({{",".join(v.idxfields)}});
|
||||
{%- endfor -%}
|
||||
COMMENT ON TABLE {{summary[0].name}} IS '{{summary[0].title}}';
|
||||
{% for field in fields %}
|
||||
COMMENT ON COLUMN {{summary[0].name}}.{{field.name}} is '{{field.title}}';
|
||||
{% endfor %}
|
||||
"""
|
45
sqlor/ddl_template_postgresql.py
Executable file
45
sqlor/ddl_template_postgresql.py
Executable file
@ -0,0 +1,45 @@
|
||||
postgresql_ddl_tmpl = """{% macro typeStr(type,len,dec) %}
|
||||
{%- if type=='str' -%}
|
||||
VARCHAR({{len}})
|
||||
{%- elif type=='char' -%}
|
||||
CHAR({{len}})
|
||||
{%- elif type=='long' or type=='int' or type=='short' -%}
|
||||
NUMERIC(30,0)
|
||||
{%- elif type=='float' or type=='double' or type=='ddouble' -%}
|
||||
NUMERIC({{len}},{{dec}})
|
||||
{%- elif type=='date' -%}
|
||||
DATE
|
||||
{%- elif type=='time' -%}
|
||||
TIME
|
||||
{%- elif type=='timestamp' -%}
|
||||
TIMESTAMP
|
||||
{%- else -%}
|
||||
{{type}}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
{% macro nullStr(nullable) %}
|
||||
{%- if nullable=='no' -%}
|
||||
NOT NULL
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% macro primary() %}
|
||||
,PRIMARY KEY({{','.join(summary[0].primary)}})
|
||||
{% endmacro %}
|
||||
DROP TABLE IF EXISTS {{summary[0].name}};
|
||||
CREATE TABLE {{summary[0].name}}
|
||||
(
|
||||
{% for field in fields %}
|
||||
{{field.name}} {{typeStr(field.type,field.length,field.dec)}} {{nullStr(field.nullable)}}{%- if not loop.last -%},{%- endif -%}
|
||||
{% endfor %}
|
||||
{% if summary[0].primary and len(summary[0].primary)>0 %}
|
||||
{{primary()}}
|
||||
{% endif %}
|
||||
);
|
||||
{% for v in indexes %}
|
||||
CREATE {% if v.idxtype=='unique' %}UNIQUE{% endif %} INDEX {{summary[0].name}}_{{v.name}} ON {{summary[0].name}}({{",".join(v.idxfields)}});
|
||||
{%- endfor -%}
|
||||
COMMENT ON TABLE {{summary[0].name}} IS '{{summary[0].title}}';
|
||||
{% for field in fields %}
|
||||
COMMENT ON COLUMN {{summary[0].name}}.{{field.name}} is '{{field.title}}';
|
||||
{% endfor %}
|
||||
"""
|
37
sqlor/ddl_template_sqlite3.py
Executable file
37
sqlor/ddl_template_sqlite3.py
Executable file
@ -0,0 +1,37 @@
|
||||
sqlite3_ddl_tmpl = """{% macro typeStr(type,len,dec) %}
|
||||
{%- if type in ['str', 'char', 'date', 'time', 'datetime', 'timestamp'] -%}
|
||||
TEXT
|
||||
{%- elif type in ['long', 'int', 'short', 'longlong' ] -%}
|
||||
int
|
||||
{%- elif type in ['float', 'double', 'ddouble'] -%}
|
||||
real
|
||||
{%- elif type=='bin' -%}
|
||||
blob
|
||||
{%- else -%}
|
||||
{{type}}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
{% macro nullStr(nullable) %}
|
||||
{%- if nullable=='no' -%}
|
||||
NOT NULL
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% macro primary() %}
|
||||
,primary key({{','.join(summary[0].primary)}})
|
||||
{% endmacro %}
|
||||
drop table if exists {{summary[0].name}};
|
||||
CREATE TABLE {{summary[0].name}}
|
||||
(
|
||||
{% for field in fields %}
|
||||
`{{field.name}}` {{typeStr(field.type,field.length,field.dec)}} {{nullStr(field.nullable)}}{%- if not loop.last -%},{%- endif -%} {%if field.title -%} -- {{field.title}}{%- endif %}
|
||||
{% endfor %}
|
||||
{% if summary[0].primary and len(summary[0].primary)>0 %}
|
||||
{{primary()}}
|
||||
{% endif %}
|
||||
)
|
||||
{% if summary[0].title %} --{{summary[0].title}}{% endif %}
|
||||
;
|
||||
{% for v in indexes %}
|
||||
CREATE {% if v.idxtype=='unique' %}UNIQUE{% endif %} INDEX {{summary[0].name}}_{{v.name}} ON {{summary[0].name}}({{",".join(v.idxfields)}});
|
||||
{%- endfor -%}
|
||||
"""
|
49
sqlor/ddl_template_sqlserver.py
Executable file
49
sqlor/ddl_template_sqlserver.py
Executable file
@ -0,0 +1,49 @@
|
||||
sqlserver_ddl_tmpl = """{% macro typeStr(type,len,dec) %}
|
||||
{%- if type=='str' -%}
|
||||
NVARCHAR({{len}})
|
||||
{%- elif type=='char' -%}
|
||||
CHAR({{len}})
|
||||
{%- elif type=='long' or type=='int' or type=='short' -%}
|
||||
NUMERIC
|
||||
{%- elif type=='float' or type=='double' or type=='ddouble' -%}
|
||||
numeric({{len}},{{dec}})
|
||||
{%- elif type=='date' or type=='time' -%}
|
||||
DATE
|
||||
{%- elif type=='timestamp' -%}
|
||||
TIMESTAMP
|
||||
{%- elif type=='text' -%}
|
||||
NVARCHAR(MAX)
|
||||
{%- elif type=='bin' -%}
|
||||
IMAGE
|
||||
{%- else -%}
|
||||
{{type}}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
{% macro nullStr(nullable) %}
|
||||
{%- if nullable=='no' -%}
|
||||
NOT NULL
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro primary() %}
|
||||
,primary key({{','.join(summary[0].primary)}})
|
||||
{% endmacro %}
|
||||
|
||||
drop table dbo.{{summary[0].name}};
|
||||
CREATE TABLE dbo.{{summary[0].name}}
|
||||
(
|
||||
{% for field in fields %}
|
||||
{{field.name}} {{typeStr(field.type,field.length,field.dec)}} {{nullStr(field.nullable)}}{%- if not loop.last -%},{%- endif -%}
|
||||
{% endfor %}
|
||||
{% if summary[0].primary and len(summary[0].primary)>0 %}
|
||||
{{primary()}}
|
||||
{% endif %}
|
||||
)
|
||||
{% for v in indexes %}
|
||||
CREATE {% if v.idxtype=='unique' %}UNIQUE{% endif %} INDEX {{summary[0].name}}_{{v.name}} ON {{summary[0].name}}({{",".join(v.idxfields)}});
|
||||
{%- endfor -%}
|
||||
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'{{summary[0].title}}' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'{{summary[0].name}}'
|
||||
{% for field in fields %}
|
||||
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'{{field.title}}' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'{{summary[0].name}}', @level2type=N'COLUMN',@level2name=N'{{field.name}}'
|
||||
{% endfor %}
|
||||
"""
|
180
sqlor/filter.py
Executable file
180
sqlor/filter.py
Executable file
@ -0,0 +1,180 @@
|
||||
# -*- coding:utf8 -*-
|
||||
"""
|
||||
过滤器解释器
|
||||
解释json格式的SQL查询过滤
|
||||
过滤支持:
|
||||
双目关系运算符:
|
||||
AND
|
||||
OR
|
||||
单目关系运算符:
|
||||
NOT
|
||||
表达式:
|
||||
表达关系有:=,<>,>,<,>=,<=,in,not in
|
||||
a=b格式的
|
||||
{
|
||||
"and":[
|
||||
{
|
||||
"field":'field1'
|
||||
"op":"=",
|
||||
"const":1
|
||||
"var":"var1"
|
||||
},
|
||||
{
|
||||
"or":[...]
|
||||
}
|
||||
{
|
||||
"not":{...}
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
try:
|
||||
import ujson as json
|
||||
except:
|
||||
import json
|
||||
|
||||
class DBFilter(object):
|
||||
operators = [
|
||||
"=",
|
||||
"!=",
|
||||
"IN",
|
||||
"NOT IN",
|
||||
">",
|
||||
">=",
|
||||
"<",
|
||||
"<=",
|
||||
"IS NULL",
|
||||
"IS NOT NULL",
|
||||
"LIKE",
|
||||
"NOT LIKE"
|
||||
]
|
||||
logic = [
|
||||
"AND",
|
||||
"OR",
|
||||
"NOT"
|
||||
]
|
||||
def __init__(self,filterjson):
|
||||
if isinstance(filterjson, str):
|
||||
filterjson = json.loads(filterjson)
|
||||
self.filterjson = filterjson
|
||||
|
||||
def gen(self, ns={}):
|
||||
self.consts = {}
|
||||
ret = self._genFilterSQL(self.filterjson, ns)
|
||||
ns.update(self.consts)
|
||||
return ret
|
||||
|
||||
def get_variables(self):
|
||||
return self.get_filters_variables(self.filterjson)
|
||||
|
||||
def get_filters_variables(self, filters):
|
||||
vs = {}
|
||||
keys = [ k for k in filters.keys() ]
|
||||
if len(keys) == 1:
|
||||
fs = filters[keys[0]]
|
||||
if isinstance(fs, list):
|
||||
for f in fs:
|
||||
v = self.get_filters_variables(f)
|
||||
if v:
|
||||
vs.update(v)
|
||||
return vs
|
||||
else:
|
||||
v = self.get_filters_variables(fs)
|
||||
if v:
|
||||
vs.update(v)
|
||||
return vs
|
||||
if 'var' in keys:
|
||||
return {
|
||||
filters['var']:filters['field']
|
||||
}
|
||||
return None
|
||||
|
||||
def _genFilterSQL(self,fj, ns):
|
||||
keys = [ i for i in fj.keys()]
|
||||
if len(keys) == 1:
|
||||
key = keys[0]
|
||||
if key.lower() in ['and','or']:
|
||||
if type(fj[key]) != type([]) or len(fj[key])<2:
|
||||
raise Exception(key + ':' + json.dumps(fj[key]) + ':is not a array, or array length < 2')
|
||||
subsqls = [self._genFilterSQL(f, ns) for f in fj[key]]
|
||||
subsqls = [ s for s in subsqls if s is not None]
|
||||
if len(subsqls) < 1:
|
||||
return None
|
||||
if len(subsqls) < 2:
|
||||
return subsqls[0]
|
||||
|
||||
a = ' %s ' % key
|
||||
sql = a.join(subsqls)
|
||||
if key == 'or':
|
||||
return ' (%s) ' % sql
|
||||
return sql
|
||||
if key.lower() == 'not':
|
||||
if type(fj[key]) != type({}):
|
||||
raise Exception(key + ':' + json.dumps(fj[key]) + ':is not a dict')
|
||||
a = ' %s ' % key
|
||||
sql = self._genFilterSQL(fj[key], ns)
|
||||
if not sql:
|
||||
return None
|
||||
return ' not (%s) ' % sql
|
||||
return self._genFilterItems(fj, ns)
|
||||
|
||||
def _genFilterItems(self,fj, ns):
|
||||
keys = fj.keys()
|
||||
assert 'field' in keys
|
||||
assert 'op' in keys
|
||||
assert 'const' in keys or 'var' in keys or fj['op'].upper() in ['IS NULL', 'IS NOT NULL']
|
||||
op = fj.get('op').upper()
|
||||
assert op in self.operators
|
||||
|
||||
if op in ['IS NULL', 'IS NOT NULL']:
|
||||
return f"{fj['field']} {op}"
|
||||
|
||||
var = fj.get('var')
|
||||
if var and not var in ns.keys():
|
||||
return None
|
||||
|
||||
if 'const' in keys:
|
||||
cnt = len(self.consts.keys())
|
||||
name = f'filter_const_{cnt}'
|
||||
self.consts.update({name:fj.get('const')})
|
||||
sql = '%s %s ${%s}$' % (fj.get('field'), fj.get('op'), name)
|
||||
return sql
|
||||
|
||||
sql = '%s %s ${%s}$' % (fj.get('field'), fj.get('op'), fj.get('var'))
|
||||
return sql
|
||||
|
||||
def default_filterjson(fields: list, ns: dict):
|
||||
fj = {}
|
||||
c = [ {
|
||||
'field':k,
|
||||
'op':'=',
|
||||
'var':k
|
||||
} for k in ns.keys() if k in fields ]
|
||||
print(f'default_filterjson():{c=}')
|
||||
if len(c) < 1:
|
||||
return None
|
||||
if len(c) < 2:
|
||||
return c[0]
|
||||
return {
|
||||
'AND':c
|
||||
}
|
||||
|
||||
if __name__ == '__main__':
|
||||
fj = {
|
||||
"AND":[
|
||||
{
|
||||
"field":'field1',
|
||||
"op":"=",
|
||||
"var":"name"
|
||||
},
|
||||
{
|
||||
"field":'del_flg',
|
||||
"op":"=",
|
||||
"const":"0"
|
||||
}]
|
||||
}
|
||||
|
||||
dbf = DBFilter(fj)
|
||||
print(fj)
|
||||
print(dbf.gen({'name':'joe'}))
|
||||
print(f'{dbf.consts=}')
|
12
sqlor/mongo.desc
Executable file
12
sqlor/mongo.desc
Executable file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"driver":"motor",
|
||||
"async_mode":true,
|
||||
"dbname":"test",
|
||||
"kwargs":{
|
||||
"host":"localhost",
|
||||
"port":20017,
|
||||
"user":"test",
|
||||
"password":"test123",
|
||||
"dbname":"test"
|
||||
}
|
||||
}
|
174
sqlor/mssqlor.py
Executable file
174
sqlor/mssqlor.py
Executable file
@ -0,0 +1,174 @@
|
||||
# -*- coding:utf8 -*-
|
||||
from .sor import SQLor
|
||||
from .ddl_template_sqlserver import sqlserver_ddl_tmpl
|
||||
|
||||
class MsSqlor(SQLor):
|
||||
ddl_template = sqlserver_ddl_tmpl
|
||||
db2modelTypeMapping = {
|
||||
'bit':'short',
|
||||
'tinyint':'short',
|
||||
'date':'date',
|
||||
'bigint':'long',
|
||||
'smallint':'short',
|
||||
'int':'long',
|
||||
'decimal':'float',
|
||||
'numeric':'float',
|
||||
'smallmoney':'float',
|
||||
'money':'float',
|
||||
'real':'float',
|
||||
'float':'float',
|
||||
'datetime':'date',
|
||||
'timestamp':'timestamp',
|
||||
'uniqueidentifier':'timestamp',
|
||||
'char':'char',
|
||||
'varchar':'str',
|
||||
'text':'text',
|
||||
'nchar':'str',
|
||||
'nvarchar':'str',
|
||||
'ntext':'text',
|
||||
'binary':'str',
|
||||
'varbinary':'str',
|
||||
'image':'file',
|
||||
}
|
||||
model2dbTypemapping = {
|
||||
'date':'datetime',
|
||||
'time':'date',
|
||||
'timestamp':'timestamp',
|
||||
'str':'nvarchar',
|
||||
'char':'char',
|
||||
'short':'int',
|
||||
'long':'numeric',
|
||||
'float':'numeric',
|
||||
'text':'ntext',
|
||||
'file':'image',
|
||||
}
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='pymssql'
|
||||
|
||||
def grammar(self):
|
||||
return {
|
||||
'select':select_stmt,
|
||||
}
|
||||
|
||||
def placeHolder(self,varname,pos=None):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return '%s'
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
if type(dataList) == type({}):
|
||||
d = [ i for i in dataList.values()]
|
||||
else:
|
||||
d = [ i['value'] for i in dataList]
|
||||
return tuple(d)
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
return u"""select *
|
||||
from (
|
||||
select row_number() over(order by $[sort]$) as _row_id,page_s.*
|
||||
from (%s) page_s
|
||||
) A
|
||||
where _row_id >= $[from_line]$ and _row_id < $[end_line]$"""
|
||||
|
||||
def tablesSQL(self):
|
||||
sqlcmd = u"""select
|
||||
lower(d.name) as name,
|
||||
lower(cast(Isnull(f.VALUE,d.name) as nvarchar )) title
|
||||
from sysobjects d
|
||||
left join sys.extended_properties f on d.id = f.major_id and f.minor_id = 0
|
||||
where d.xtype = 'U'"""
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self,tablename=None):
|
||||
sqlcmd=u"""SELECT name = lower(a.name)
|
||||
,type = b.name
|
||||
,length = Columnproperty(a.id,a.name,'PRECISION')
|
||||
,dec = Isnull(Columnproperty(a.id,a.name,'Scale'),null)
|
||||
,nullable = CASE
|
||||
WHEN a.isnullable = 1 THEN 'yes'
|
||||
ELSE 'no'
|
||||
END
|
||||
,title = lower(cast(Isnull(g.[value],a.name) as nvarchar) )
|
||||
,table_name = lower(d.name)
|
||||
FROM syscolumns a
|
||||
LEFT JOIN systypes b
|
||||
ON a.xusertype = b.xusertype
|
||||
INNER JOIN sysobjects d
|
||||
ON (a.id = d.id)
|
||||
AND (d.xtype = 'U')
|
||||
AND (d.name <> 'dtproperties')
|
||||
INNER JOIN sys.all_objects c
|
||||
ON d.id=c.object_id
|
||||
AND schema_name(schema_id)='dbo'
|
||||
LEFT JOIN sys.extended_properties g
|
||||
ON (a.id = g.major_id)
|
||||
AND (a.colid = g.minor_id)
|
||||
LEFT JOIN sys.extended_properties f
|
||||
ON (d.id = f.major_id)
|
||||
AND (f.minor_id = 0)"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ where lower(d.name)='%s'
|
||||
ORDER BY a.id,a.colorder""" % tablename.lower()
|
||||
else:
|
||||
sqlcmd = sqlcmd + """ ORDER BY a.id,a.colorder"""
|
||||
return sqlcmd
|
||||
|
||||
def fkSQL(self,tablename=None):
|
||||
sqlcmd = u"""select
|
||||
MainCol.name AS field -- [主表列名]
|
||||
,oSub.name AS fk_table -- [子表名称],
|
||||
,SubCol.name AS fk_field -- [子表列名],
|
||||
from
|
||||
sys.foreign_keys fk
|
||||
JOIN sys.all_objects oSub
|
||||
ON (fk.parent_object_id = oSub.object_id)
|
||||
JOIN sys.all_objects oMain
|
||||
ON (fk.referenced_object_id = oMain.object_id)
|
||||
JOIN sys.foreign_key_columns fkCols
|
||||
ON (fk.object_id = fkCols.constraint_object_id)
|
||||
JOIN sys.columns SubCol
|
||||
ON (oSub.object_id = SubCol.object_id
|
||||
AND fkCols.parent_column_id = SubCol.column_id)
|
||||
JOIN sys.columns MainCol
|
||||
ON (oMain.object_id = MainCol.object_id
|
||||
AND fkCols.referenced_column_id = MainCol.column_id)"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ where lower(oMain.name) = '%s'""" % tablename.lower()
|
||||
|
||||
return sqlcmd
|
||||
|
||||
def pkSQL(self,tablename=None):
|
||||
sqlcmd = u"""select
|
||||
lower(a.table_name) as table_name,
|
||||
lower(b.column_name) as field_name
|
||||
from information_schema.table_constraints a
|
||||
inner join information_schema.constraint_column_usage b
|
||||
on a.constraint_name = b.constraint_name
|
||||
where a.constraint_type = 'PRIMARY KEY'"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ and lower(a.table_name) = '%s'""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def indexesSQL(self,tablename=None):
|
||||
sqlcmd = """SELECT
|
||||
index_name=lower(IDX.Name),
|
||||
index_type=IDX.is_unique,
|
||||
column_name=lower(C.Name)
|
||||
FROM sys.indexes IDX
|
||||
INNER JOIN sys.index_columns IDXC
|
||||
ON IDX.[object_id]=IDXC.[object_id]
|
||||
AND IDX.index_id=IDXC.index_id
|
||||
LEFT JOIN sys.key_constraints KC
|
||||
ON IDX.[object_id]=KC.[parent_object_id]
|
||||
AND IDX.index_id=KC.unique_index_id
|
||||
INNER JOIN sys.objects O
|
||||
ON O.[object_id]=IDX.[object_id]
|
||||
INNER JOIN sys.columns C
|
||||
ON O.[object_id]=C.[object_id]
|
||||
AND O.type='U'
|
||||
AND O.is_ms_shipped=0
|
||||
AND IDXC.Column_id=C.Column_id"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ where lower(O.name)='%s'""" % tablename.lower()
|
||||
return sqlcmd
|
143
sqlor/mysqlor.py
Executable file
143
sqlor/mysqlor.py
Executable file
@ -0,0 +1,143 @@
|
||||
# -*- coding:utf8 -*-
|
||||
from appPublic.argsConvert import ArgsConvert,ConditionConvert
|
||||
|
||||
from .sor import SQLor
|
||||
from .const import ROWS
|
||||
from .ddl_template_mysql import mysql_ddl_tmpl
|
||||
class MySqlor(SQLor):
|
||||
ddl_template = mysql_ddl_tmpl
|
||||
db2modelTypeMapping = {
|
||||
'tinyint':'short',
|
||||
'smallint':'short',
|
||||
'mediumint':'long',
|
||||
'int':'long',
|
||||
'bigint':'long',
|
||||
'decimal':'float',
|
||||
'double':'float',
|
||||
'float':'float',
|
||||
'char':'char',
|
||||
'varchar':'str',
|
||||
'tinyblob':'text',
|
||||
'tinytext':'text',
|
||||
'mediumblob':'text',
|
||||
'mediumtext':'text',
|
||||
'blob':'text',
|
||||
'text':'text',
|
||||
'mediumblob':'text',
|
||||
'mediumtext':'text',
|
||||
'longblob':'bin',
|
||||
'longtext':'text',
|
||||
'barbinary':'text',
|
||||
'binary':'text',
|
||||
'date':'date',
|
||||
'time':'time',
|
||||
'datetime':'datetime',
|
||||
'timestamp':'datestamp',
|
||||
'year':'short',
|
||||
}
|
||||
model2dbTypemapping = {
|
||||
'date':'date',
|
||||
'time':'date',
|
||||
'timestamp':'timestamp',
|
||||
'str':'varchar',
|
||||
'char':'char',
|
||||
'short':'int',
|
||||
'long':'bigint',
|
||||
'float':'double',
|
||||
'text':'longtext',
|
||||
'bin':'longblob',
|
||||
'file':'longblob',
|
||||
}
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
if name=='pymysql':
|
||||
return True
|
||||
return False
|
||||
|
||||
def grammar(self):
|
||||
return {
|
||||
'select':select_stmt,
|
||||
}
|
||||
|
||||
def placeHolder(self,varname,pos=None):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return '%s'
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
if type(dataList) == type({}):
|
||||
d = [ i for i in dataList.values()]
|
||||
else:
|
||||
d = [ i['value'] for i in dataList]
|
||||
return tuple(d)
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
return """select *, row_number() over(order by $[sort]$) as row_num_ from (%s) A limit $[from_line]$, $[rows]$"""
|
||||
return """select * from (%s) A order by $[sort]$
|
||||
limit $[from_line]$,$[rows]$"""
|
||||
|
||||
def tablesSQL(self):
|
||||
sqlcmd = """SELECT lower(TABLE_NAME) as name, lower(TABLE_COMMENT) as title FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '%s'""" % self.dbdesc.get('dbname','unknown')
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self,tablename=None):
|
||||
sqlcmd="""
|
||||
select
|
||||
lower(column_name) as name,
|
||||
data_type as type,
|
||||
case when character_maximum_length is null then NUMERIC_PRECISION
|
||||
else character_maximum_length end
|
||||
as length,
|
||||
NUMERIC_SCALE as 'dec',
|
||||
lower(is_nullable) as nullable,
|
||||
column_comment as title,
|
||||
lower(table_name) as table_name
|
||||
from information_schema.columns where lower(TABLE_SCHEMA) = '%s' """ % self.dbdesc.get('dbname','unknown').lower()
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """and lower(table_name)='%s';""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def fkSQL(self,tablename=None):
|
||||
sqlcmd = """SELECT C.TABLE_SCHEMA 拥有者,
|
||||
C.REFERENCED_TABLE_NAME 父表名称 ,
|
||||
C.REFERENCED_COLUMN_NAME 父表字段 ,
|
||||
C.TABLE_NAME 子表名称,
|
||||
C.COLUMN_NAME 子表字段,
|
||||
C.CONSTRAINT_NAME 约束名,
|
||||
T.TABLE_COMMENT 表注释,
|
||||
R.UPDATE_RULE 约束更新规则,
|
||||
R.DELETE_RULE 约束删除规则
|
||||
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE C
|
||||
JOIN INFORMATION_SCHEMA. TABLES T
|
||||
ON T.TABLE_NAME = C.TABLE_NAME
|
||||
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R
|
||||
ON R.TABLE_NAME = C.TABLE_NAME
|
||||
AND R.CONSTRAINT_NAME = C.CONSTRAINT_NAME
|
||||
AND R.REFERENCED_TABLE_NAME = C.REFERENCED_TABLE_NAME
|
||||
WHERE C.REFERENCED_TABLE_NAME IS NOT NULL ;
|
||||
and C.TABLE_SCHEMA = '%s'
|
||||
""" % self.dbdesc.get('dbname','unknown').lower()
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + " and C.REFERENCED_TABLE_NAME = '%s'" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def pkSQL(self,tablename=None):
|
||||
sqlcmd = """SELECT distinct column_name as name FROM INFORMATION_SCHEMA.`KEY_COLUMN_USAGE` WHERE table_name='%s' AND constraint_name='PRIMARY'
|
||||
""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def indexesSQL(self,tablename=None):
|
||||
sqlcmd = """SELECT DISTINCT
|
||||
lower(index_name) as index_name,
|
||||
case NON_UNIQUE
|
||||
when 1 then 'unique'
|
||||
else ''
|
||||
end as is_unique,
|
||||
lower(column_name) as column_name
|
||||
FROM
|
||||
information_schema.statistics
|
||||
WHERE
|
||||
table_schema = '%s'""" % self.dbdesc.get('dbname','unknown')
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ AND table_name = '%s'""" % tablename.lower()
|
||||
return sqlcmd
|
130
sqlor/oracleor.py
Executable file
130
sqlor/oracleor.py
Executable file
@ -0,0 +1,130 @@
|
||||
from .sor import SQLor
|
||||
from .ddl_template_oracle import oracle_ddl_tmpl
|
||||
class Oracleor(SQLor):
|
||||
ddl_template = oracle_ddl_tmpl
|
||||
db2modelTypeMapping = {
|
||||
'char':'char',
|
||||
'nchar':'str',
|
||||
'varchar':'str',
|
||||
'varchar2':'str',
|
||||
'nvarchar2':'str',
|
||||
'number':'long',
|
||||
'integer':'long',
|
||||
'binary_float':'float',
|
||||
'binary_double':'float',
|
||||
'float':'float',
|
||||
'timestamp':'timestamp',
|
||||
'timestamp with time zone':'timestamp',
|
||||
'timestamp with local time zone':'timestamp',
|
||||
'interval year to moth':'date',
|
||||
'interval day to second':'timestamp',
|
||||
'clob':'text',
|
||||
'nclob':'text',
|
||||
'blob':'file',
|
||||
'bfile':'file',
|
||||
'date':'date',
|
||||
}
|
||||
model2dbTypemapping = {
|
||||
'date':'date',
|
||||
'time':'date',
|
||||
'timestamp':'date',
|
||||
'str':'varchar2',
|
||||
'char':'char',
|
||||
'short':'number',
|
||||
'long':'number',
|
||||
'float':'number',
|
||||
'text':'nclob',
|
||||
'file':'blob',
|
||||
}
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='cx_Oracle'
|
||||
|
||||
def grammar(self):
|
||||
return {
|
||||
'select':select_stmt,
|
||||
}
|
||||
|
||||
def placeHolder(self,varname,pos=None):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return ':%s' % varname
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
if type(dataList) == type({}):
|
||||
return dataList
|
||||
d = {}
|
||||
[ d.update({i['name']:i['value']}) for i in dataList ]
|
||||
return d
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
return u"""select *
|
||||
from (
|
||||
select page_s.*,rownum row_id
|
||||
from (%s) page_s
|
||||
order by $[sort]$
|
||||
)
|
||||
where row_id >=$[from_line]$ and row_id < $[end_line]$"""
|
||||
|
||||
def tablesSQL(self):
|
||||
sqlcmd = """select
|
||||
lower(table_name) as name,
|
||||
lower(decode(comments,null,table_name,comments)) as title
|
||||
from USER_TAB_COMMENTS where table_type = 'TABLE'"""
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self,tablename=None):
|
||||
sqlcmd="""select lower(utc.COLUMN_NAME) name
|
||||
,utc.DATA_TYPE type
|
||||
,utc.DATA_LENGTH length
|
||||
,utc.data_scale dec
|
||||
,case when utc.nullable = 'Y' then 'yes' else 'no' end nullable
|
||||
,lower(nvl(ucc.comments,utc.COLUMN_NAME)) title
|
||||
,lower(utc.table_name) as table_name
|
||||
from user_tab_cols utc left join USER_COL_COMMENTS ucc on utc.table_name = ucc.table_name and utc.COLUMN_NAME = ucc.COLUMN_NAME"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ where lower(utc.table_name) = '%s'""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def fkSQL(self,tablename=None):
|
||||
tablename = tablename.lower()
|
||||
sqlcmd = """select
|
||||
distinct(ucc.column_name) as field,rela.table_name as fk_table,rela.column_name as fk_field
|
||||
from
|
||||
user_constraints uc,user_cons_columns ucc,
|
||||
(
|
||||
select t2.table_name,t2.column_name,t1.r_constraint_name
|
||||
from user_constraints t1,user_cons_columns t2
|
||||
where t1.r_constraint_name=t2.constraint_name
|
||||
) rela
|
||||
where
|
||||
uc.constraint_name=ucc.constraint_name
|
||||
and uc.r_constraint_name=rela.r_constraint_name"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ and lower(uc.table_name)='%s'""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def pkSQL(self,tablename=None):
|
||||
sqlcmd = """
|
||||
select
|
||||
lower(col.table_name) table_name,
|
||||
lower(col.column_name) as field_name
|
||||
from
|
||||
user_constraints con,user_cons_columns col
|
||||
where
|
||||
con.constraint_name=col.constraint_name and con.constraint_type='P'"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ and lower(col.table_name)='%s'""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def indexesSQL(self,tablename=None):
|
||||
sqlcmd = """select
|
||||
lower(a.index_name) index_name,
|
||||
lower(a.UNIQUENESS) is_unique,
|
||||
lower(b.column_name) column_name
|
||||
from user_indexes a, user_ind_columns b
|
||||
where a.index_name = b.index_name"""
|
||||
if tablename is not None:
|
||||
sqlcmd += """ and lower(a.table_name) = lower('%s')""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
171
sqlor/postgresqlor.py
Executable file
171
sqlor/postgresqlor.py
Executable file
@ -0,0 +1,171 @@
|
||||
from .sor import SQLor
|
||||
from .ddl_template_postgresql import postgresql_ddl_tmpl
|
||||
|
||||
class PostgreSQLor(SQLor):
|
||||
ddl_template = postgresql_ddl_tmpl
|
||||
db2modelTypeMapping = {
|
||||
'smallint':'short',
|
||||
'integer':'long',
|
||||
'bigint':'llong',
|
||||
'decimal':'float',
|
||||
'numeric':'float',
|
||||
'real':'float',
|
||||
'double':'float',
|
||||
'serial':'long',
|
||||
'bigserial':'llong',
|
||||
'char':'char',
|
||||
'character':'char',
|
||||
'varchar':'str',
|
||||
'character varying':'str',
|
||||
'text':'text',
|
||||
'timestamp':'timestamp',
|
||||
'date':'date',
|
||||
'time':'time',
|
||||
'boolean':'char',
|
||||
'bytea':'file'
|
||||
}
|
||||
model2dbTypemapping = {
|
||||
'date':'date',
|
||||
'time':'date',
|
||||
'timestamp':'timestamp',
|
||||
'str':'varchar',
|
||||
'char':'char',
|
||||
'short':'smallint',
|
||||
'long':'integer',
|
||||
'float':'numeric',
|
||||
'text':'text',
|
||||
'file':'bytea',
|
||||
}
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='psycopg2' or name=='pyguass'
|
||||
|
||||
def grammar(self):
|
||||
return {
|
||||
'select':select_stmt,
|
||||
}
|
||||
|
||||
def placeHolder(self,varname,i):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return '%%(%s)s' % varname
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
if type(dataList) == type({}):
|
||||
return dataList
|
||||
d = { i['name']:i['value'] for i in dataList }
|
||||
return d
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
return u"""select *
|
||||
from (
|
||||
select page_s.*,rownum row_id
|
||||
from (%s) page_s
|
||||
order by $[sort]$
|
||||
)
|
||||
where row_id >=$[from_line]$ and row_id < $[end_line]$"""
|
||||
|
||||
def tablesSQL(self):
|
||||
sqlcmd = """select x.name, y.description as title
|
||||
from
|
||||
(select a.name,c.oid
|
||||
from
|
||||
(select lower(tablename) as name from pg_tables where schemaname='public') a,
|
||||
pg_class c
|
||||
where a.name = c.relname) x
|
||||
left join pg_description y
|
||||
on x.oid=y.objoid
|
||||
and y.objsubid='0'"""
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self,tablename=None):
|
||||
sqlcmd="""SELECT
|
||||
a.attname AS name,
|
||||
t.typname AS type,
|
||||
case t.typname
|
||||
when 'varchar' then a.atttypmod - 4
|
||||
when 'numeric' then (a.atttypmod - 4) / 65536
|
||||
else null
|
||||
end as length,
|
||||
case t.typname
|
||||
when 'numeric' then (a.atttypmod - 4) %% 65536
|
||||
else null
|
||||
end as dec,
|
||||
case a.attnotnull
|
||||
when 't' then 'no'
|
||||
when 'f' then 'yes'
|
||||
end as nullable,
|
||||
b.description AS title
|
||||
FROM pg_class c, pg_attribute a
|
||||
LEFT JOIN pg_description b
|
||||
ON a.attrelid = b.objoid
|
||||
AND a.attnum = b.objsubid, pg_type t
|
||||
WHERE lower(c.relname) = '%s'
|
||||
AND a.attnum > 0
|
||||
AND a.attrelid = c.oid
|
||||
AND a.atttypid = t.oid
|
||||
ORDER BY a.attnum;
|
||||
""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def fkSQL(self,tablename=None):
|
||||
tablename = tablename.lower()
|
||||
sqlcmd = """select
|
||||
distinct(ucc.column_name) as field,rela.table_name as fk_table,rela.column_name as fk_field
|
||||
from
|
||||
user_constraints uc,user_cons_columns ucc,
|
||||
(
|
||||
select t2.table_name,t2.column_name,t1.r_constraint_name
|
||||
from user_constraints t1,user_cons_columns t2
|
||||
where t1.r_constraint_name=t2.constraint_name
|
||||
) rela
|
||||
where
|
||||
uc.constraint_name=ucc.constraint_name
|
||||
and uc.r_constraint_name=rela.r_constraint_name"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ and lower(uc.table_name)='%s'""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def pkSQL(self,tablename=None):
|
||||
sqlcmd="""
|
||||
select
|
||||
pg_attribute.attname as field_name,
|
||||
lower(pg_class.relname) as table_name
|
||||
from pg_constraint
|
||||
inner join pg_class
|
||||
on pg_constraint.conrelid = pg_class.oid
|
||||
inner join pg_attribute
|
||||
on pg_attribute.attrelid = pg_class.oid
|
||||
and pg_attribute.attnum = pg_constraint.conkey[1]
|
||||
inner join pg_type
|
||||
on pg_type.oid = pg_attribute.atttypid
|
||||
where lower(pg_class.relname) = '%s'
|
||||
and pg_constraint.contype='p'
|
||||
""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def indexesSQL(self,tablename=None):
|
||||
sqlcmd = """select
|
||||
i.relname as index_name,
|
||||
case ix.INDISUNIQUE
|
||||
when 't' then 'unique'
|
||||
else ''
|
||||
end as is_unique,
|
||||
a.attname as column_name
|
||||
from
|
||||
pg_class t,
|
||||
pg_class i,
|
||||
pg_index ix,
|
||||
pg_attribute a
|
||||
where
|
||||
t.oid = ix.indrelid
|
||||
and i.oid = ix.indexrelid
|
||||
and a.attrelid = t.oid
|
||||
and a.attnum = ANY(ix.indkey)
|
||||
and t.relkind = 'r'
|
||||
and lower(t.relname) = '%s'
|
||||
order by
|
||||
t.relname,
|
||||
i.relname""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
27
sqlor/records.py
Executable file
27
sqlor/records.py
Executable file
@ -0,0 +1,27 @@
|
||||
from appPublic.dictObject import DictObject
|
||||
|
||||
class Records:
|
||||
def __init__(self,klass=DictObject):
|
||||
self._records = []
|
||||
self.klass = klass
|
||||
|
||||
def add(self,rec):
|
||||
obj = self.klass(**rec)
|
||||
self._records.append(obj)
|
||||
|
||||
def get(self):
|
||||
return self._records
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
self.start = 0
|
||||
self.end = len(self._records)
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self.start < self.end:
|
||||
d = self._records[self.start]
|
||||
self.start = self.start + 1
|
||||
return d
|
||||
else:
|
||||
raise StopIteration
|
35
sqlor/runsql.py
Executable file
35
sqlor/runsql.py
Executable file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/python3
|
||||
import sys
|
||||
import codecs
|
||||
from sqlor.dbpools import runSQL
|
||||
import asyncio
|
||||
|
||||
def appinit():
|
||||
if len(sys.argv) < 4:
|
||||
print(f'usage:\n {sys.argv[0]} path dbname sqlfile [k=v ...] \n')
|
||||
sys.exit(1)
|
||||
p = ProgramPath()
|
||||
if len(sys.argv) > 1:
|
||||
p = sys.argv[1]
|
||||
config = getConfig(p)
|
||||
DBPools(config.databases)
|
||||
|
||||
|
||||
async def run(ns):
|
||||
with codecs.open(sys.argv[3], 'r', 'utf-8') as f:
|
||||
sql = f.read()
|
||||
await runSQL(sys.argv[2], sql, ns)
|
||||
|
||||
if __name__ == '__main__':
|
||||
ns = {}
|
||||
for x in sys.argv[3:]:
|
||||
try:
|
||||
k,v = x.split('=')
|
||||
ns.update({k:v})
|
||||
except Exception as e:
|
||||
print(x, 'key-value pair expected')
|
||||
print(e)
|
||||
|
||||
appinit()
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(run(ns))
|
684
sqlor/sor.py
Executable file
684
sqlor/sor.py
Executable file
@ -0,0 +1,684 @@
|
||||
from traceback import print_exc
|
||||
import os
|
||||
import decimal
|
||||
from asyncio import coroutine
|
||||
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
|
||||
import sys
|
||||
from datetime import datetime, date
|
||||
import codecs
|
||||
import re
|
||||
import json
|
||||
from appPublic.myImport import myImport
|
||||
from appPublic.dictObject import DictObject
|
||||
from appPublic.unicoding import uDict
|
||||
from appPublic.myTE import MyTemplateEngine
|
||||
from appPublic.objectAction import ObjectAction
|
||||
from appPublic.argsConvert import ArgsConvert,ConditionConvert
|
||||
from appPublic.registerfunction import RegisterFunction
|
||||
from appPublic.log import info
|
||||
from .filter import DBFilter
|
||||
|
||||
def db_type_2_py_type(o):
|
||||
if isinstance(o,decimal.Decimal):
|
||||
return float(o)
|
||||
if isinstance(o,datetime):
|
||||
# return '%020d' % int(o.timestamp() * 1000)
|
||||
return str(o)
|
||||
if isinstance(o, date):
|
||||
return '%04d-%02d-%02d' % (o.year, o.month, o.day)
|
||||
return o
|
||||
|
||||
class SQLorException(Exception,object):
|
||||
def __int__(self,**kvs):
|
||||
supper(SQLException,self).__init__(self,**kvs)
|
||||
self.dic = {
|
||||
'response':'error',
|
||||
'errtype':'SQLor',
|
||||
'errmsg':supper(SQLException,self).message,
|
||||
}
|
||||
|
||||
def __str__(self):
|
||||
return 'errtype:%s,errmsg=%s' % (self.dic['errtype'],self.dic['errmsg'])
|
||||
|
||||
def setValues(params,ns):
|
||||
r = ns.get(params,os.getenv(params))
|
||||
return r
|
||||
|
||||
def findNamedParameters(sql):
|
||||
"""
|
||||
return a list of named parameters
|
||||
"""
|
||||
re1 = '\$\{[_a-zA-Z_][a-zA-Z_0-9]*\}'
|
||||
params1 = re.findall(re1,sql)
|
||||
return params1
|
||||
|
||||
|
||||
def uniParams(params1):
|
||||
ret = []
|
||||
for i in params1:
|
||||
if i not in ret:
|
||||
ret.append(i)
|
||||
return ret
|
||||
|
||||
def readsql(fn):
|
||||
f = codecs.open(fn,'r','utf-8')
|
||||
b = f.read()
|
||||
f.close()
|
||||
return b
|
||||
|
||||
class SQLor(object):
|
||||
def __init__(self,dbdesc=None,sqltp = '$[',sqlts = ']$',sqlvp = '${',sqlvs = '}$'):
|
||||
self.conn = None
|
||||
self.cur = None
|
||||
self.async_mode = False
|
||||
self.sqltp = sqltp
|
||||
self.sqlts = sqlts
|
||||
self.sqlvp = sqlvp
|
||||
self.sqlvs = sqlvs
|
||||
self.dbdesc = dbdesc
|
||||
self.dbname = self.dbdesc.get('dbname')
|
||||
if self.dbname:
|
||||
self.dbname = self.dbname.lower()
|
||||
self.writer = None
|
||||
self.convfuncs = {}
|
||||
self.cc = ConditionConvert()
|
||||
self.dataChanged = False
|
||||
self.metadatas={}
|
||||
|
||||
async def get_schema(self):
|
||||
def concat_idx_info(idxs):
|
||||
x = []
|
||||
n = None
|
||||
for i in idxs:
|
||||
if not n or n.index_name != i.index_name:
|
||||
if n:
|
||||
x.append(n)
|
||||
n = i
|
||||
n.column_name = [i.column_name]
|
||||
else:
|
||||
n.column_name.append(i.column_name)
|
||||
return x
|
||||
|
||||
tabs = await self.tables()
|
||||
schemas = []
|
||||
for t in tabs:
|
||||
primary = await self.primary(t.name)
|
||||
# print('primary=', primary)
|
||||
indexes = concat_idx_info(await self.indexes(t.name))
|
||||
fields = await self.fields(t.name)
|
||||
primary_fields = [f.field_name for f in primary]
|
||||
if len(primary_fields)>0:
|
||||
t.primary = [f.field_name for f in primary]
|
||||
x = {}
|
||||
x['summary'] = [t]
|
||||
x['indexes'] = indexes
|
||||
x['fields'] = fields
|
||||
schemas.append(x)
|
||||
return schemas
|
||||
|
||||
def setMeta(self,tablename,meta):
|
||||
self.metadatas[tablename.lower()] = meta
|
||||
|
||||
def getMeta(self,tablename):
|
||||
return self.metadatas.get(tablename.lower(),None)
|
||||
|
||||
def removeMeta(self,tablename):
|
||||
if getMeta(self.tablename):
|
||||
del self.metadatas[tablename.lower()]
|
||||
|
||||
def setCursor(self,async_mode,conn,cur):
|
||||
self.async_mode = async_mode
|
||||
self.conn = conn
|
||||
self.cur = cur
|
||||
|
||||
def getConn(self):
|
||||
return self.conn
|
||||
|
||||
def setConvertFunction(self,typ,func):
|
||||
self.convfuncs.update({typ:func})
|
||||
|
||||
def convert(self,typ,value):
|
||||
if self.convfuncs.get(typ,None) is not None:
|
||||
return self.convfuncs[typ](value)
|
||||
return value
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='sqlor'
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
return ""
|
||||
|
||||
def placeHolder(self,varname,pos=None):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return '?'
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
return [ i.get('value',None) for i in dataList]
|
||||
|
||||
def dataList(self,k,v):
|
||||
a = []
|
||||
a.append({'name':k,'value':v})
|
||||
return a
|
||||
|
||||
def cursor(self):
|
||||
return self.cur
|
||||
|
||||
def recordCnt(self,sql):
|
||||
ret = u"""select count(*) rcnt from (%s) rowcount_table""" % sql
|
||||
return ret
|
||||
|
||||
def sortSQL(self, sql, NS):
|
||||
sort = NS.get('sort',None)
|
||||
if sort is None:
|
||||
return sql
|
||||
if isinstance(sort, list):
|
||||
sort = ','.join(sort)
|
||||
return sql + ' ORDER BY ' + sort
|
||||
|
||||
def pagingSQL(self,sql,paging,NS):
|
||||
"""
|
||||
default it not support paging
|
||||
"""
|
||||
page = int(NS.get(paging['pagename'],1))
|
||||
rows = int(NS.get(paging['rowsname'],80))
|
||||
sort = NS.get(paging.get('sortname','sort'),None)
|
||||
if isinstance(sort, list):
|
||||
sort = ','.join(sort)
|
||||
if not sort:
|
||||
return sql
|
||||
if page < 1:
|
||||
page = 1
|
||||
from_line = (page - 1) * rows
|
||||
end_line = page * rows
|
||||
psql = self.pagingSQLmodel()
|
||||
ns={
|
||||
'from_line':from_line,
|
||||
'end_line':end_line,
|
||||
'rows':rows,
|
||||
'sort':sort
|
||||
}
|
||||
ac = ArgsConvert('$[',']$')
|
||||
psql = ac.convert(psql,ns)
|
||||
retSQL=psql % sql
|
||||
return retSQL
|
||||
|
||||
def filterSQL(self,sql,filters,NS):
|
||||
ac = ArgsConvert('$[',']$')
|
||||
fbs = []
|
||||
for f in filters:
|
||||
vars = ac.findAllVariables(f)
|
||||
if len(vars) > 0:
|
||||
ignoreIt = False
|
||||
for v in vars:
|
||||
if not NS.get(v,False):
|
||||
ignoreIt = True
|
||||
if not ignoreIt:
|
||||
f = ac.convert(f,NS)
|
||||
else:
|
||||
f = '1=1'
|
||||
fbs.append(f)
|
||||
fb = ' '.join(fbs)
|
||||
retsql = u"""select * from (%s) filter_table where %s""" % (sql,fb)
|
||||
return retsql
|
||||
|
||||
async def runVarSQL(self,cursor,sql,NS):
|
||||
"""
|
||||
using a opened cursor to run a SQL statment with variable, the variable is setup in NS namespace
|
||||
return a cursor with data
|
||||
"""
|
||||
markedSQL, datas = self.maskingSQL(sql,NS)
|
||||
datas = self.dataConvert(datas)
|
||||
try:
|
||||
if self.async_mode:
|
||||
return await cursor.execute(markedSQL,datas)
|
||||
else:
|
||||
return cursor.execute(markedSQL,datas)
|
||||
|
||||
except Exception as e:
|
||||
print( "markedSQL=",markedSQL,':',datas,':',e)
|
||||
print_exc()
|
||||
raise e
|
||||
|
||||
def maskingSQL(self,org_sql,NS):
|
||||
"""
|
||||
replace all ${X}$ format variable exception named by '__mainsql__' in sql with '%s',
|
||||
and return the marked sql sentent and variable list
|
||||
sql is a sql statment with variable formated in '${X}$
|
||||
the '__mainsql__' variable use to identify the main sql will outout data.
|
||||
NS is the name space the variable looking for, it is a variable dictionary
|
||||
return (MarkedSQL,list_of_variable)
|
||||
"""
|
||||
sqltextAC = ArgsConvert(self.sqltp,self.sqlts)
|
||||
sqlargsAC = ArgsConvert(self.sqlvp,self.sqlvs)
|
||||
sql1 = sqltextAC.convert(org_sql,NS)
|
||||
cc = ConditionConvert()
|
||||
sql1 = cc.convert(sql1,NS)
|
||||
vars = sqlargsAC.findAllVariables(sql1)
|
||||
phnamespace = {}
|
||||
[phnamespace.update({v:self.placeHolder(v,i)}) for i,v in enumerate(vars)]
|
||||
m_sql = sqlargsAC.convert(sql1,phnamespace)
|
||||
newdata = []
|
||||
for v in vars:
|
||||
if v != '__mainsql__':
|
||||
value = sqlargsAC.getVarValue(v,NS,None)
|
||||
newdata += self.dataList(v,value)
|
||||
|
||||
return (m_sql,newdata)
|
||||
|
||||
def getSqlType(self,sql):
|
||||
"""
|
||||
return one of "qry", "dml" and "ddl"
|
||||
ddl change the database schema
|
||||
dml change the database data
|
||||
qry query data
|
||||
"""
|
||||
|
||||
a = sql.lstrip(' \t\n\r')
|
||||
a = a.lower()
|
||||
al = a.split(' ')
|
||||
if al[0] == 'select':
|
||||
return 'qry'
|
||||
if al[0] in ['update','delete','insert']:
|
||||
return 'dml'
|
||||
return 'ddl'
|
||||
|
||||
async def execute(self,sql,value,callback,**kwargs):
|
||||
sqltype = self.getSqlType(sql)
|
||||
cur = self.cursor()
|
||||
ret = await self.runVarSQL(cur,sql,value)
|
||||
if sqltype == 'qry' and callback is not None:
|
||||
fields = [ i[0].lower() for i in cur.description ]
|
||||
rec = None
|
||||
if self.async_mode:
|
||||
rec = await cur.fetchone()
|
||||
else:
|
||||
rec = cur.fetchone()
|
||||
|
||||
while rec is not None:
|
||||
dic = {}
|
||||
for i in range(len(fields)):
|
||||
dic.update({fields[i] : db_type_2_py_type(rec[i])})
|
||||
dic = DictObject(**dic)
|
||||
callback(dic,**kwargs)
|
||||
if self.async_mode:
|
||||
rec = await cur.fetchone()
|
||||
else:
|
||||
rec = cur.fetchone()
|
||||
if sqltype == 'dml':
|
||||
self.dataChanged = True
|
||||
return ret
|
||||
|
||||
async def executemany(self,sql,values):
|
||||
cur = self.cursor()
|
||||
markedSQL,datas = self.maskingSQL(sql,{})
|
||||
datas = [ self.dataConvert(d) for d in values ]
|
||||
if self.async_mode:
|
||||
await cur.executemany(markedSQL,datas)
|
||||
else:
|
||||
cur.executemany(markedSQL,datas)
|
||||
|
||||
def pivotSQL(self,tablename,rowFields,columnFields,valueFields):
|
||||
def maxValue(columnFields,valueFields,cfvalues):
|
||||
sql = ''
|
||||
for f in valueFields:
|
||||
i = 0
|
||||
for field in columnFields:
|
||||
for v in cfvalues[field]:
|
||||
sql += """
|
||||
,sum(%s_%d) %s_%d""" % (f,i,f,i)
|
||||
i+=1
|
||||
return sql
|
||||
def casewhen(columnFields,valueFields,cfvalues):
|
||||
sql = ''
|
||||
for f in valueFields:
|
||||
i = 0
|
||||
for field in columnFields:
|
||||
for v in cfvalues[field]:
|
||||
if v is None:
|
||||
sql += """,case when %s is null then %s
|
||||
else 0 end as %s_%d -- %s
|
||||
""" % (field,f,f,i,v)
|
||||
else:
|
||||
sql += """,case when trim(%s) = trim('%s') then %s
|
||||
else 0 end as %s_%d -- %s
|
||||
""" % (field,v,f,f,i,v)
|
||||
|
||||
i += 1
|
||||
return sql
|
||||
|
||||
cfvalues={}
|
||||
for field in columnFields:
|
||||
sqlstring = 'select distinct %s from %s' % (field,tablename)
|
||||
v = []
|
||||
self.execute(sqlstring,{},lambda x: v.append(x))
|
||||
cfvalues[field] = [ i[field] for i in v ]
|
||||
|
||||
sql ="""
|
||||
select """ + ','.join(rowFields)
|
||||
sql += maxValue(columnFields,valueFields,cfvalues)
|
||||
sql += """ from
|
||||
(select """ + ','.join(rowFields)
|
||||
sql += casewhen(columnFields,valueFields,cfvalues)
|
||||
sql += """
|
||||
from %s)
|
||||
group by %s""" % (tablename,','.join(rowFields))
|
||||
return sql
|
||||
|
||||
async def pivot(self,desc,tablename,rowFields,columnFields,valueFields):
|
||||
sql = self.pivotSQL(tablename,rowFields,columnFields,valueFields)
|
||||
desc['sql_string'] = sql
|
||||
ret = []
|
||||
return await self.execute(sql,{},lambda x:ret.append(x))
|
||||
|
||||
def isSelectSql(self,sql):
|
||||
return self.getSqlType(sql) == 'qry'
|
||||
|
||||
def getSQLfromDesc(self,desc):
|
||||
sql = ''
|
||||
if 'sql_file' in desc.keys():
|
||||
sql = readsql(desc['sql_file'])
|
||||
else:
|
||||
sql = desc['sql_string']
|
||||
return sql
|
||||
|
||||
async def record_count(self,desc,NS):
|
||||
cnt_desc = {}
|
||||
cnt_desc.update(desc)
|
||||
sql = self.getSQLfromDesc(desc)
|
||||
if desc.get('sql_file',False):
|
||||
del cnt_desc['sql_file']
|
||||
cnt_desc['sql_string'] = self.recordCnt(sql)
|
||||
class Cnt:
|
||||
def __init__(self):
|
||||
self.recs = []
|
||||
def handler(self,rec):
|
||||
self.recs.append(rec)
|
||||
|
||||
c = Cnt()
|
||||
await self.runSQL(cnt_desc,NS,c.handler)
|
||||
t = c.recs[0]['rcnt']
|
||||
return t
|
||||
|
||||
async def runSQLPaging(self,desc,NS):
|
||||
total = await self.record_count(desc,NS)
|
||||
recs = await self.pagingdata(desc,NS)
|
||||
data = {
|
||||
"total":total,
|
||||
"rows":recs
|
||||
}
|
||||
return data
|
||||
|
||||
async def pagingdata(self,desc,NS):
|
||||
paging_desc = {}
|
||||
paging_desc.update(desc)
|
||||
paging_desc.update(
|
||||
{
|
||||
"paging":{
|
||||
"rowsname":"rows",
|
||||
"pagename":"page",
|
||||
"sortname":"sort"
|
||||
}
|
||||
})
|
||||
if desc.get('sortfield',False):
|
||||
NS['sort'] = desc.get('sortfield')
|
||||
sql = self.getSQLfromDesc(desc)
|
||||
if desc.get('sql_file',False):
|
||||
del cnt_desc['sql_file']
|
||||
paging_desc['sql_string'] = self.pagingSQL(sql,
|
||||
paging_desc.get('paging'),NS)
|
||||
|
||||
class Cnt:
|
||||
def __init__(self):
|
||||
self.recs = []
|
||||
def handler(self,rec):
|
||||
self.recs.append(rec)
|
||||
|
||||
c = Cnt()
|
||||
await self.runSQL(paging_desc,NS,c.handler)
|
||||
return c.recs
|
||||
|
||||
async def resultFields(self,desc,NS):
|
||||
NS.update(rows=1,page=1)
|
||||
r = await self.pagingdata(desc,NS)
|
||||
ret = [ {'name':i[0],'type':i[1]} for i in self.cur.description ]
|
||||
return ret
|
||||
|
||||
async def runSQL(self,desc,NS,callback,**kw):
|
||||
class RecordHandler:
|
||||
def __init__(self,ns,name):
|
||||
self.ns = ns
|
||||
self.name = name
|
||||
self.ns[name] = []
|
||||
|
||||
def handler(self,rec):
|
||||
self.ns[self.name].append(rec)
|
||||
|
||||
cur = self.cursor()
|
||||
sql = self.getSQLfromDesc(desc)
|
||||
if self.isSelectSql(sql):
|
||||
if callback is None:
|
||||
klass = desc.get('dataname','dummy')
|
||||
if klass is not None:
|
||||
rh = RecordHandler(NS,klass)
|
||||
callback = rh.handler
|
||||
else:
|
||||
callback = None
|
||||
await self.execute(sql,NS,callback)
|
||||
|
||||
async def sqlExecute(self,desc,NS):
|
||||
return await self.execute(desc,NS,None)
|
||||
|
||||
async def sqlExe(self,sql,ns):
|
||||
ret = []
|
||||
r = await self.execute(sql,ns,
|
||||
callback=lambda x:ret.append(x))
|
||||
sqltype = self.getSqlType(sql)
|
||||
if sqltype == 'dml':
|
||||
return r
|
||||
|
||||
return ret
|
||||
|
||||
async def sqlPaging(self,sql,ns):
|
||||
ret = []
|
||||
dic = {
|
||||
"sql_string":sql
|
||||
}
|
||||
page = ns.get('page')
|
||||
if not page:
|
||||
ns['page'] = 1
|
||||
|
||||
total = await self.record_count(dic,ns)
|
||||
rows = await self.pagingdata(dic,ns)
|
||||
return {
|
||||
'total':total,
|
||||
'rows':rows
|
||||
}
|
||||
|
||||
async def tables(self):
|
||||
sqlstring = self.tablesSQL()
|
||||
ret = []
|
||||
await self.execute(sqlstring,{},lambda x:ret.append(x))
|
||||
return ret
|
||||
|
||||
def indexesSQL(self,tablename):
|
||||
"""
|
||||
record of {
|
||||
index_name,
|
||||
index_type,
|
||||
table_name,
|
||||
column_name
|
||||
}
|
||||
"""
|
||||
return None
|
||||
|
||||
async def indexes(self,tablename=None):
|
||||
sqlstring = self.indexesSQL(tablename.lower())
|
||||
if sqlstring is None:
|
||||
return []
|
||||
recs = []
|
||||
await self.execute(sqlstring,{},lambda x:recs.append(x))
|
||||
return recs
|
||||
|
||||
async def fields(self,tablename=None):
|
||||
sqlstring = self.fieldsSQL(tablename)
|
||||
recs = []
|
||||
await self.execute(sqlstring,{},lambda x:recs.append(x))
|
||||
ret = []
|
||||
for r in recs:
|
||||
r.update({'type':self.db2modelTypeMapping.get(r['type'].lower(),'unknown')})
|
||||
r.update({'name':r['name'].lower()})
|
||||
ret.append(r)
|
||||
return ret
|
||||
|
||||
async def primary(self,tablename):
|
||||
sqlstring = self.pkSQL(tablename)
|
||||
recs = []
|
||||
await self.execute(sqlstring,{},lambda x:recs.append(x))
|
||||
# print('sql=', sqlstring, 'recs=', recs)
|
||||
return recs
|
||||
|
||||
async def fkeys(self,tablename):
|
||||
sqlstring = self.fkSQL(tablename)
|
||||
recs = []
|
||||
await self.execute(sqlstring,{},lambda x:recs.append(x))
|
||||
return recs
|
||||
|
||||
async def createTable(self,tabledesc):
|
||||
te = MyTemplateEngine([],'utf8','utf8')
|
||||
desc = {
|
||||
"sql_string":te.renders(self.ddl_template,tabledesc)
|
||||
}
|
||||
return await self.sqlExecute(desc,{})
|
||||
|
||||
async def getTableDesc(self,tablename):
|
||||
desc = self.getMeta(tablename)
|
||||
if desc:
|
||||
return desc
|
||||
desc = {}
|
||||
summary = [ i for i in await self.tables() if tablename.lower() == i['name'].lower() ]
|
||||
print(f'{summary=}, {tablename=}, {desc=}')
|
||||
pris = await self.primary(tablename)
|
||||
primary = [i['name'] for i in pris ]
|
||||
summary[0]['primary'] = primary
|
||||
desc['summary'] = summary
|
||||
desc['fields'] = await self.fields(tablename=tablename)
|
||||
desc['indexes'] = []
|
||||
idx = {}
|
||||
idxrecs = await self.indexes(tablename)
|
||||
for idxrec in idxrecs:
|
||||
if idxrec['index_name'] == 'primary':
|
||||
continue
|
||||
if idxrec['index_name'] != idx.get('name',None):
|
||||
if idx != {}:
|
||||
desc['indexes'].append(idx)
|
||||
idx = {
|
||||
}
|
||||
idx['name'] = idxrec['index_name']
|
||||
idx['idxtype'] = 'unique' if idxrec['is_unique'] else 'index'
|
||||
idx['idxfields'] = []
|
||||
idx['idxfields'].append(idxrec['column_name'])
|
||||
if idx != {}:
|
||||
desc['indexes'].append(idx)
|
||||
self.setMeta(tablename,desc)
|
||||
return desc
|
||||
|
||||
async def rollback(self):
|
||||
if self.async_mode:
|
||||
await self.conn.rollback()
|
||||
else:
|
||||
self.conn.rollback()
|
||||
self.dataChanged = False
|
||||
|
||||
async def commit(self):
|
||||
if self.async_mode:
|
||||
await self.conn.commit()
|
||||
else:
|
||||
self.conn.commit()
|
||||
self.datachanged = False
|
||||
|
||||
async def I(self,tablename):
|
||||
return await self.getTableDesc(tablename)
|
||||
|
||||
async def C(self,tablename,ns):
|
||||
desc = await self.I(tablename)
|
||||
keys = ns.keys()
|
||||
fields = [ i['name'] for i in desc['fields'] if i['name'] in keys ]
|
||||
fns = ','.join(fields)
|
||||
vfns = ','.join(['${%s}$' % n for n in fields ])
|
||||
sql = 'insert into %s.%s (%s) values (%s)' % (self.dbname, tablename,fns,vfns)
|
||||
rf = RegisterFunction()
|
||||
rfname = f'{self.dbname}:{tablename}:c:before'
|
||||
ret = await rf.exe(rfname, ns)
|
||||
if isinstance(ret, dict):
|
||||
ns.update(ret)
|
||||
r = await self.runSQL({'sql_string':sql},ns.copy(), None)
|
||||
await rf.exe(f'{self.dbname}:{tablename}:c:after', ns)
|
||||
return r
|
||||
|
||||
async def R(self,tablename,ns,filters=None):
|
||||
desc = await self.I(tablename)
|
||||
sql = 'select * from %s.%s' % (self.dbname, tablename.lower())
|
||||
if filters:
|
||||
dbf = DBFilter(filters)
|
||||
sub = dbf.genFilterString(ns)
|
||||
if sub:
|
||||
sql = '%s where %s' % (sql, sub)
|
||||
|
||||
else:
|
||||
fields = [ i['name'] for i in desc['fields'] ]
|
||||
c = [ '%s=${%s}$' % (k,k) for k in ns.keys() if k in fields ]
|
||||
if len(c) > 0:
|
||||
sql = '%s where %s' % (sql,' and '.join(c))
|
||||
|
||||
if 'page' in ns.keys():
|
||||
if not 'sort' in ns.keys():
|
||||
ns['sort'] = desc['summary'][0]['primary'][0]
|
||||
dic = {
|
||||
"sql_string":sql
|
||||
}
|
||||
total = await self.record_count(dic,ns)
|
||||
rows = await self.pagingdata(dic,ns)
|
||||
return {
|
||||
'total':total,
|
||||
'rows':rows
|
||||
}
|
||||
else:
|
||||
if ns.get('sort'):
|
||||
sql = self.sortSQL(sql, ns)
|
||||
return await self.sqlExe(sql,ns)
|
||||
|
||||
async def U(self,tablename,ns):
|
||||
desc = await self.I(tablename)
|
||||
fields = [ i['name'] for i in desc['fields']]
|
||||
condi = [ i for i in desc['summary'][0]['primary']]
|
||||
newData = [ i for i in ns.keys() if i not in condi and i in fields]
|
||||
c = [ '%s = ${%s}$' % (i,i) for i in condi ]
|
||||
u = [ '%s = ${%s}$' % (i,i) for i in newData ]
|
||||
c_str = ' and '.join(c)
|
||||
u_str = ','.join(u)
|
||||
sql = 'update %s.%s set %s where %s' % (self.dbname, tablename,
|
||||
u_str,c_str)
|
||||
rf = RegisterFunction()
|
||||
ret = await rf.exe(f'{self.dbname}:{tablename}:u:before',ns)
|
||||
if isinstance(ret, dict):
|
||||
ns.update(ret)
|
||||
r = await self.runSQL({'sql_string':sql},ns.copy() ,None)
|
||||
await rf.exe(f'{self.dbname}:{tablename}:u:after',ns)
|
||||
return r
|
||||
|
||||
async def D(self,tablename,ns):
|
||||
desc = await self.I(tablename)
|
||||
fields = [ i['name'] for i in desc['fields']]
|
||||
condi = [ i for i in desc['summary'][0]['primary']]
|
||||
c = [ '%s = ${%s}$' % (i,i) for i in condi ]
|
||||
c_str = ' and '.join(c)
|
||||
sql = 'delete from %s.%s where %s' % (self.dbname, tablename,c_str)
|
||||
rf = RegisterFunction()
|
||||
ret = await rf.exe(f'{self.dbname}:{tablename}:d:before', ns)
|
||||
if isinstance(ret, dict):
|
||||
ns.update(ret)
|
||||
r = await self.runSQL({'sql_string':sql},ns,None)
|
||||
ns = await rf.exe(f'{self.dbname}:{tablename}:d:after', ns)
|
||||
return r
|
||||
|
100
sqlor/sqlite3or.py
Executable file
100
sqlor/sqlite3or.py
Executable file
@ -0,0 +1,100 @@
|
||||
import re
|
||||
from .sor import SQLor
|
||||
|
||||
class SQLite3or(SQLor):
|
||||
db2modelTypeMapping = {
|
||||
'text':'str',
|
||||
'blob':'file',
|
||||
'int':'long',
|
||||
'integer':'long',
|
||||
'real':'float',
|
||||
}
|
||||
model2dbTypemapping = {
|
||||
'date':'text',
|
||||
'time':'text',
|
||||
'timestamp':'text',
|
||||
'str':'text',
|
||||
'char':'text',
|
||||
'short':'int',
|
||||
'long':'int',
|
||||
'float':'real',
|
||||
'text':'text',
|
||||
'file':'blob',
|
||||
}
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='sqlite3'
|
||||
|
||||
def placeHolder(self,varname,pos=None):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return '?'
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
if type(dataList) == type({}):
|
||||
d = [ i for i in dataList.values()]
|
||||
else:
|
||||
d = [ i['value'] for i in dataList]
|
||||
return tuple(d)
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
sql = u"""select * from (%s) order by $[sort]$ limit $[from_line]$,$[end_line]$"""
|
||||
return sql
|
||||
|
||||
def tablesSQL(self):
|
||||
sqlcmd = u"""select name, tbl_name as title from sqlite_master where upper(type) = 'TABLE'"""
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self,tablename):
|
||||
# sqlcmd="""PRAGMA table_info('%s')""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
def fields(self,tablename):
|
||||
m = u'(\w+)\(((\d+)(,(\d+)){0,1})\){0,1}'
|
||||
k = re.compile(m)
|
||||
def typesplit(typ):
|
||||
d = k.search(typ)
|
||||
if d is None:
|
||||
return typ,0,0
|
||||
|
||||
return d.group(1),int(d.group(3) if d.group(3) is not None else 0 ),int(d.group(5) if d.group(5) is not None else 0)
|
||||
|
||||
sqlstring = self.fieldsSQL(tablename)
|
||||
recs = []
|
||||
self.execute(sqlstring,callback=lambda x:recs.append(x))
|
||||
for r in recs:
|
||||
t,l,d = typesplit(r['type'])
|
||||
r['type'] = t
|
||||
r['length'] = int(l)
|
||||
r['dec'] = int(d)
|
||||
r['title'] = r['name']
|
||||
ret = []
|
||||
for r in recs:
|
||||
r.update({'type':self.db2modelTypeMapping.get(r['type'].lower(),'text')})
|
||||
r.update({'name':r['name'].lower()})
|
||||
ret.append(r)
|
||||
return ret
|
||||
|
||||
def fkSQL(self,tablename):
|
||||
sqlcmd = ""
|
||||
return sqlcmd
|
||||
|
||||
def fkeys(self,tablename):
|
||||
return []
|
||||
|
||||
def primary(self,tablename):
|
||||
recs = self.fields(tablename)
|
||||
ret = [ {'field':r['name']} for r in recs if r['pk'] == 1 ]
|
||||
return ret
|
||||
|
||||
def pkSQL(self,tablename):
|
||||
sqlcmd = ""
|
||||
return sqlcmd
|
||||
|
||||
def indexesSQL(self,tablename=None):
|
||||
sqlcmd = """select * from sqlite_master
|
||||
where lower(type) = 'index'
|
||||
"""
|
||||
if tablename:
|
||||
sqlcmd += "and lower(tbl_name)='" + tablename.lower() + "' "
|
||||
return sqlcmd
|
2
sqlor/version.py
Executable file
2
sqlor/version.py
Executable file
@ -0,0 +1,2 @@
|
||||
# fixed sor.py C function bug.
|
||||
__version__ = "0.1.3"
|
47
test/primary.py
Executable file
47
test/primary.py
Executable file
@ -0,0 +1,47 @@
|
||||
import asyncio
|
||||
|
||||
from sqlor.dbpools import DBPools
|
||||
|
||||
dbs={
|
||||
"aiocfae":{
|
||||
"driver":"aiomysql",
|
||||
"async_mode":True,
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"cfae":{
|
||||
"driver":"mysql.connector",
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
pool = DBPools(dbs,loop=loop)
|
||||
async def printTables(dbname):
|
||||
r = await pool.getTables(dbname)
|
||||
print('tables=',r)
|
||||
|
||||
async def printFields(dbname,tablename):
|
||||
r = await pool.getTableFields(dbname,tablename)
|
||||
print(dbname,tablename,'fields=',r)
|
||||
|
||||
async def printPrimary(dbname,tablename):
|
||||
r = await pool.getTablePrimaryKey(dbname,tablename)
|
||||
print(dbname,tablename,'primary key=',r)
|
||||
|
||||
loop.run_until_complete(printTables('cfae'))
|
||||
loop.run_until_complete(printFields('cfae','product'))
|
||||
loop.run_until_complete(printPrimary('cfae','product'))
|
35
test/sqlite3_sql.py
Executable file
35
test/sqlite3_sql.py
Executable file
@ -0,0 +1,35 @@
|
||||
import sys
|
||||
import os
|
||||
import asyncio
|
||||
import codecs
|
||||
from sqlor.dbpools import DBPools
|
||||
|
||||
async def exesqls(sqllines):
|
||||
sqls = sqllines.split(';')
|
||||
async with DBPools().sqlorContext('db') as sor:
|
||||
for sql in sqls:
|
||||
await sor.sqlExe(sql, {})
|
||||
|
||||
async def main():
|
||||
with codecs.open(sys.argv[2],'r', 'utf-8') as f:
|
||||
txt = f.read()
|
||||
await exesqls(txt)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 3:
|
||||
print(f'Usage:{sys.argv[0]} sqlite3_db_file sqlfile')
|
||||
sys.exit(1)
|
||||
dbs = {
|
||||
"db":{
|
||||
"driver":"aiosqlite",
|
||||
"kwargs":{
|
||||
"dbname":sys.argv[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
DBPools(dbs)
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(main())
|
||||
|
||||
|
44
test/t1.py
Executable file
44
test/t1.py
Executable file
@ -0,0 +1,44 @@
|
||||
import asyncio
|
||||
|
||||
from sqlor.dbpools import DBPools
|
||||
|
||||
dbs={
|
||||
"aiocfae":{
|
||||
"driver":"aiomysql",
|
||||
"async_mode":True,
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"cfae":{
|
||||
"driver":"mysql.connector",
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
pool = DBPools(dbs,loop=loop)
|
||||
|
||||
async def paging():
|
||||
@pool.runSQLPaging
|
||||
def sql(db,ns):
|
||||
return {
|
||||
"sql_string":"select * from product",
|
||||
}
|
||||
x = await sql('aiocfae',{'rows':5,'page':1,"sort":"productid"})
|
||||
print('x=',x['total'],len(x['rows']))
|
||||
|
||||
|
||||
loop.run_until_complete(paging())
|
64
test/t2.py
Executable file
64
test/t2.py
Executable file
@ -0,0 +1,64 @@
|
||||
import asyncio
|
||||
|
||||
from sqlor.dbpools import DBPools
|
||||
|
||||
dbs={
|
||||
"tasks":{
|
||||
"driver":"aiomysql",
|
||||
"async_mode":True,
|
||||
"coding":"utf8",
|
||||
"dbname":"tasks",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"tasks",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"aiocfae":{
|
||||
"driver":"aiomysql",
|
||||
"async_mode":True,
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"cfae":{
|
||||
"driver":"mysql.connector",
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
pool = DBPools(dbs,loop=loop)
|
||||
|
||||
async def testfunc():
|
||||
@pool.runSQL
|
||||
def sql(db,ns,callback):
|
||||
return {
|
||||
"sql_string":"select * from product",
|
||||
}
|
||||
x = await sql('cfae',{},print)
|
||||
|
||||
async def testfunc1():
|
||||
@pool.runSQL
|
||||
def sql(db,ns,callback):
|
||||
return {
|
||||
"sql_string":"select * from timeobjects",
|
||||
}
|
||||
print('testfunc1(),test tasks database select')
|
||||
x = await sql('tasks',{},print)
|
||||
|
||||
loop.run_until_complete(testfunc())
|
||||
loop.run_until_complete(testfunc1())
|
60
test/test.py
Executable file
60
test/test.py
Executable file
@ -0,0 +1,60 @@
|
||||
import asyncio
|
||||
|
||||
from sqlor.dbpools import DBPools
|
||||
from sqlor.records import Records
|
||||
|
||||
dbs={
|
||||
"aiocfae":{
|
||||
"driver":"aiomysql",
|
||||
"async_mode":True,
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
},
|
||||
"cfae":{
|
||||
"driver":"mysql.connector",
|
||||
"coding":"utf8",
|
||||
"dbname":"cfae",
|
||||
"kwargs":{
|
||||
"user":"test",
|
||||
"db":"cfae",
|
||||
"password":"test123",
|
||||
"host":"localhost"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
pool = DBPools(dbs,loop=loop)
|
||||
|
||||
async def testfunc1():
|
||||
@pool.runSQL
|
||||
def sql(db,ns,callback):
|
||||
return {
|
||||
"sql_string":"select * from product",
|
||||
}
|
||||
recs = Records()
|
||||
x = await sql('cfae',{},recs.add)
|
||||
print('--------------%s---------------' % x)
|
||||
for r in recs:
|
||||
print(type(r),r)
|
||||
|
||||
async def testfunc2():
|
||||
@pool.runSQLResultFields
|
||||
def sql(db,ns,callback=None):
|
||||
return {
|
||||
"sql_string":"select * from product",
|
||||
}
|
||||
recs = Records()
|
||||
x = await sql('cfae',{},callback=recs.add)
|
||||
print('-------%s------' % x)
|
||||
for i in recs._records:
|
||||
print("--",i)
|
||||
|
||||
loop.run_until_complete(testfunc1())
|
||||
loop.run_until_complete(testfunc2())
|
Loading…
Reference in New Issue
Block a user