1 Star 0 Fork 0

stoneqp/supersqlite

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
setup.py 37.52 KB
一键复制 编辑 原始数据 按行查看 历史
Ajay Patel 提交于 2018-11-18 19:45 . Custom build_ext
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044
from __future__ import print_function
import fnmatch
import hashlib
import os
import shutil
import sys
import subprocess
import traceback
import tempfile
import zipfile
import distutils.sysconfig as dsc
from glob import glob
from icu_sources import icu_sources
from setuptools import find_packages
from distutils.core import setup, Extension
from setuptools.command.install import install
from setuptools.command.build_ext import build_ext
from setuptools.command.egg_info import egg_info
from setuptools import setup, Distribution
from multiprocessing import Process
try:
import pip._internal.pep425tags as pep425tags
pep425tags.get_supported()
raise Exception()
except Exception as e:
import pep425tags
try:
from urllib.request import urlretrieve
except BaseException:
from urllib import urlretrieve
PACKAGE_NAME = 'supersqlite'
PACKAGE_SHORT_NAME = 'supersqlite'
DOWNLOAD_REQ_WHEELS = []
def copy_sqlite(src, dest, apsw=False):
""" Copy the SQLite amalgamation """
shutil.copy(
os.path.join(src, 'sqlite3.c'), os.path.join(dest, 'sqlite3.c.pre.c'))
shutil.copy(
os.path.join(src, 'sqlite3.h'), os.path.join(dest, 'sqlite3.h'))
shutil.copy(
os.path.join(src, 'sqlite3ext.h'), os.path.join(dest, 'sqlite3ext.h'))
shutil.copy(
os.path.join(src, 'shell.c'), os.path.join(dest, 'shell.c'))
shutil.copy(
os.path.join(src, 'icu.cpp'), os.path.join(dest, 'icu.cpp'))
if apsw:
shutil.copy(
os.path.join(src, 'apsw_shell.c'), os.path.join(dest, 'shell.c'))
SQLITE_PRE = os.path.join(dest, 'sqlite3.c.pre.c')
SQLITE_POST = os.path.join(dest, 'sqlite3.c')
with open(SQLITE_POST, 'w+') as outfile:
with open(SQLITE_PRE, 'r') as infile:
for line in infile:
outfile.write(line)
outfile.write('''
# ifndef PLASTICITY_SUPERSQLITE_SQLITE3_C_SHIM
# define PLASTICITY_SUPERSQLITE_SQLITE3_C_SHIM 1
# ifdef sqlite3_progress_handler
# undef sqlite3_progress_handler
# endif
# ifdef sqlite3_column_decltype
# undef sqlite3_column_decltype
# endif
# ifdef sqlite3_enable_shared_cache
# undef sqlite3_enable_shared_cache
# endif\n
''' + '\n')
outfile.write(
'void sqlite3_progress_handler(sqlite3* a, int b, int (*c)(void*), void* d){ }' +
'\n')
outfile.write('''
const char *sqlite3_column_decltype(sqlite3_stmt* stmt, int col) {
int datatype = sqlite3_column_type(stmt, col);
if (datatype == SQLITE_INTEGER) {
return "integer";
} else if (datatype == SQLITE_FLOAT) {
return "float";
} else if (datatype == SQLITE_TEXT) {
return "text";
} else if (datatype == SQLITE_BLOB) {
return "blob";
} else if (datatype == SQLITE_NULL) {
return "null";
} else {
return "other";
}
}''' + '\n')
outfile.write('''
int sqlite3_enable_shared_cache(int a) {
if (a) {
return SQLITE_ERROR;
} else {
return SQLITE_OK;
}
}
''' + '\n')
outfile.write('#endif\n')
def get_modules(THIRD_PARTY, INTERNAL, PROJ_PATH,
source_for_module_with_pyinit):
""" Get all modules this package needs compiled """
PYSQLITE2 = INTERNAL + '/pysqlite2'
APSW = INTERNAL + '/apsw'
PYSQLITE = THIRD_PARTY + '/_pysqlite'
APSW_TP = THIRD_PARTY + '/_apsw'
SQLITE3 = THIRD_PARTY + '/sqlite3'
ICU = os.path.relpath(SQLITE3 + '/icu', PROJ_PATH)
includes = [
os.path.relpath(
SQLITE3, PROJ_PATH), os.path.relpath(
os.path.join(
SQLITE3, 'raw'), PROJ_PATH)]
libraries = [os.path.relpath(SQLITE3, PROJ_PATH)]
compile_args = ["-O4", "-std=c++11"]
link_args = ["-flto"]
libraries.append(ICU)
includes.append(ICU)
link_args.append('-L' + ICU)
SO_PREFIX = PACKAGE_NAME + '.third_party.sqlite3.'
SQLITE_H_PRE = os.path.relpath(
os.path.join(SQLITE3, 'sqlite3.h.pre.h'), PROJ_PATH)
SQLITE_H_POST = os.path.relpath(
os.path.join(SQLITE3, 'sqlite3.h'), PROJ_PATH)
SQLITE_PRE = os.path.relpath(
os.path.join(SQLITE3, 'sqlite3.c.pre.c'), PROJ_PATH)
SQLITE_POST = os.path.relpath(
os.path.join(SQLITE3, 'sqlite3.c'), PROJ_PATH)
ICU_POST = os.path.relpath(
os.path.join(SQLITE3, 'icu.cpp'), PROJ_PATH)
SQLITE_EXT = os.path.relpath(
os.path.join(SQLITE3, 'ext'), PROJ_PATH)
def sqlite_config(outfile):
outfile.write('#define U_DISABLE_RENAMING 1' + '\n')
outfile.write('#define SQLITE_ENABLE_DBPAGE_VTAB 1' + '\n')
outfile.write('#define SQLITE_ENABLE_DBSTAT_VTAB 1' + '\n')
outfile.write('#define SQLITE_ENABLE_FTS3 1' + '\n')
outfile.write('#define SQLITE_ENABLE_FTS3_PARENTHESIS 1' + '\n')
outfile.write('#define SQLITE_ENABLE_FTS4 1' + '\n')
outfile.write('#define SQLITE_ENABLE_FTS5 1' + '\n')
outfile.write('#define SQLITE_ENABLE_GEOPOLY 1' + '\n')
outfile.write('#define SQLITE_ENABLE_ICU 1' + '\n')
outfile.write('#define SQLITE_ENABLE_IOTRACE 1' + '\n')
outfile.write('#define SQLITE_ENABLE_JSON1 1' + '\n')
outfile.write('#define SQLITE_ENABLE_RBU 1' + '\n')
outfile.write('#define SQLITE_ENABLE_RTREE 1' + '\n')
outfile.write('#define SQLITE_ENABLE_SESSION 1' + '\n')
outfile.write('#define SQLITE_ENABLE_SNAPSHOT 1' + '\n')
outfile.write('#define SQLITE_ENABLE_STMTVTAB 1' + '\n')
outfile.write('#define SQLITE_ENABLE_STAT2 1' + '\n')
outfile.write('#define SQLITE_ENABLE_STAT3 1' + '\n')
outfile.write('#define SQLITE_ENABLE_STAT4 1' + '\n')
outfile.write('#define SQLITE_INTROSPECTION_PRAGMAS 1' + '\n')
outfile.write('#define SQLITE_SOUNDEX 1' + '\n')
# outfile.write('#define SQLITE_THREADSAFE 0' + '\n')
outfile.write('#define SQLITE_DEFAULT_MEMSTATUS 0' + '\n')
outfile.write('#define SQLITE_DEFAULT_WAL_SYNCHRONOUS 1' + '\n')
outfile.write('#define SQLITE_LIKE_DOESNT_MATCH_BLOBS 1' + '\n')
outfile.write('#define SQLITE_MAX_EXPR_DEPTH 0' + '\n')
outfile.write('#define SQLITE_OMIT_DECLTYPE 1' + '\n')
outfile.write('#define SQLITE_OMIT_PROGRESS_CALLBACK 1' + '\n')
outfile.write('#define SQLITE_OMIT_SHARED_CACHE 1' + '\n')
outfile.write('#define SQLITE_USE_ALLOCA 1' + '\n')
outfile.write('#define SQLITE_ALLOW_COVERING_INDEX_SCAN 1' + '\n')
outfile.write('#define SQLITE_DISABLE_DIRSYNC 1' + '\n')
outfile.write('#define SQLITE_ENABLE_UPDATE_DELETE_LIMIT 1' + '\n')
outfile.write('#define SQLITE_STMTJRNL_SPILL -1' + '\n')
outfile.write('#define SQLITE_TEMP_STORE 1' + '\n')
outfile.write('#define SQLITE_USE_URI 1' + '\n')
outfile.write('#define SQLITE_ENABLE_EXPLAIN_COMMENTS 1' + '\n')
outfile.write('#define SQLITE_DEFAULT_FOREIGN_KEYS 1' + '\n')
outfile.write('#define SQLITE_MAX_LENGTH 2147483647' + '\n')
outfile.write('#define SQLITE_MAX_COLUMN 32767' + '\n')
outfile.write('#define SQLITE_MAX_SQL_LENGTH 2147483647' + '\n')
outfile.write('#define SQLITE_MAX_FUNCTION_ARG 127' + '\n')
outfile.write('#define SQLITE_MAX_COMPOUND_SELECT 65536' + '\n')
outfile.write(
'#define SQLITE_MAX_LIKE_PATTERN_LENGTH 2147483647' +
'\n')
outfile.write('#define SQLITE_MAX_VARIABLE_NUMBER 1000000000' + '\n')
outfile.write('#define SQLITE_MAX_TRIGGER_DEPTH 2147483647' + '\n')
outfile.write('#define SQLITE_MAX_ATTACHED 125' + '\n')
outfile.write('#define SQLITE_MAX_PAGE_COUNT 2147483646' + '\n')
outfile.write('\n\n\n')
with open(ICU_POST, 'w+') as outfile:
outfile.write(
'''
# ifndef PLASTICITY_SUPERSQLITE_ICU_CPP
# define PLASTICITY_SUPERSQLITE_ICU_CPP 1
#define UDATA_DEBUG 1
#define U_STATIC_IMPLEMENTATION 1
#define UCONFIG_NO_REGULAR_EXPRESSIONS 0
#define U_DISABLE_RENAMING 1
#define U_COMMON_IMPLEMENTATION
#define U_COMBINED_IMPLEMENTATION
''' + '\n'.join(
['#include "' + source + '"' for source in icu_sources]
) + '''
int _supersqlite_load_icu_data(void) {
UErrorCode _PLASTICITY_SUPERSQLITE_SET_COMMON_DATA_STATUS;
udata_setCommonData((const void*)"", &_PLASTICITY_SUPERSQLITE_SET_COMMON_DATA_STATUS);
return (int) _PLASTICITY_SUPERSQLITE_SET_COMMON_DATA_STATUS;
}
# endif
''')
with open(SQLITE_H_POST, 'w+') as outfile:
sqlite_config(outfile)
with open(SQLITE_H_PRE, 'r') as infile:
for line in infile:
outfile.write(line)
outfile.write(
'''
# ifndef PLASTICITY_SUPERSQLITE_SQLITE3_H
# define PLASTICITY_SUPERSQLITE_SQLITE3_H 1
#ifdef __cplusplus
extern "C" {
#endif
int _supersqlite_load_icu_data(void);
#ifdef __cplusplus
}
#endif
# endif
''')
with open(SQLITE_POST, 'w+') as outfile:
sqlite_config(outfile)
with open(SQLITE_PRE, 'r') as infile:
for line in infile:
outfile.write(line)
outfile.write('''
# ifndef PLASTICITY_SUPERSQLITE_SQLITE3_C_EXT_SHIM
# define PLASTICITY_SUPERSQLITE_SQLITE3_C_EXT_SHIM 1
''' + '\n')
outfile.write('''
# include "ext/async/sqlite3async.c"
# include "ext/expert/sqlite3expert.c"
# include "ext/lsm1/lsm_ckpt.c"
# include "ext/lsm1/lsm_file.c"
# include "ext/lsm1/lsm_log.c"
# include "ext/lsm1/lsm_main.c"
# include "ext/lsm1/lsm_mem.c"
# include "ext/lsm1/lsm_mutex.c"
# include "ext/lsm1/lsm_shared.c"
# include "ext/lsm1/lsm_sorted.c"
# include "ext/lsm1/lsm_str.c"
# include "ext/lsm1/lsm_tree.c"
# include "ext/lsm1/lsm_unix.c"
# include "ext/lsm1/lsm_win32.c"
# include "ext/lsm1/lsm_varint.c"
# include "ext/lsm1/lsm_vtab.c"
# include "ext/userauth/userauth.c"
# include "ext/misc/dbdump.c"
# include "ext/misc/mmapwarm.c"
# include "ext/misc/normalize.c"
# include "ext/misc/scrub.c"
# include "ext/misc/vfslog.c"
# include "zlib.c"
# include "miniz_tdef.c"
# include "miniz_tinfl.c"
# include "miniz_zip.c"
''' + '\n')
outfile.write('#endif\n')
module = 'sqlite3'
pyinit_source = source_for_module_with_pyinit(module)
icu_source = [os.path.relpath(os.path.join(SQLITE3, 'icu.cpp'), PROJ_PATH)]
zlib_sources = [
os.path.relpath(
os.path.join(
SQLITE3, "zlib.c"), PROJ_PATH), os.path.relpath(
os.path.join(
SQLITE3, "miniz_tdef.c"), PROJ_PATH), os.path.relpath(
os.path.join(
SQLITE3, "miniz_tinfl.c"), PROJ_PATH), os.path.relpath(
os.path.join(
SQLITE3, "miniz_zip.c"), PROJ_PATH)]
sqlite3 = Extension(
SO_PREFIX +
'sqlite3',
sources=[SQLITE_POST] +
icu_source +
[pyinit_source],
include_dirs=includes,
library_dirs=libraries,
libraries=[
"user32",
"Advapi32",
"Kernel32"] if sys.platform == "win32" else [],
extra_compile_args=compile_args,
extra_link_args=link_args)
def sqlite_extension(ext, skip=[], module=None):
module = module or ext
pyinit_source = source_for_module_with_pyinit(module)
return Extension(
SO_PREFIX + module,
sources=([
g for g in glob(
os.path.join(
SQLITE_EXT,
ext,
'*.c')) if os.path.basename(g) not in skip] +
[pyinit_source]),
include_dirs=includes,
library_dirs=libraries,
extra_compile_args=compile_args,
extra_link_args=link_args)
def sqlite_misc_extensions(skip=[], zlib=[], windirent=[]):
miscs = []
for source in glob(os.path.join(SQLITE_EXT, 'misc', '*.c')):
if os.path.basename(source) in skip:
continue
module = os.path.basename(source)[:-2]
pyinit_source = source_for_module_with_pyinit(module)
z_sources = zlib_sources if os.path.basename(source) in zlib else []
SQLITE3_REL = os.path.relpath(SQLITE3, PROJ_PATH)
windirent_sources = [SQLITE_POST] + icu_source + [
os.path.join(SQLITE3_REL, 'raw', 'test_windirent.c')
]
windirent_sources = (
windirent_sources if os.path.basename(source) in windirent else [])
libs = (["user32", "Advapi32", "Kernel32"] if (
sys.platform == "win32" and os.path.basename(source) in windirent) else [])
miscs.append(
Extension(
SO_PREFIX +
module,
sources=[source] +
z_sources +
windirent_sources +
[pyinit_source],
include_dirs=includes,
library_dirs=libraries,
libraries=libs,
extra_compile_args=compile_args,
extra_link_args=link_args))
return miscs
lsm1 = sqlite_extension('lsm1')
userauth = sqlite_extension('userauth')
return ([sqlite3, lsm1] +
sqlite_misc_extensions(
skip=['dbdump.c', 'mmapwarm.c', 'normalize.c', 'scrub.c', 'vfslog.c'],
zlib=['compress.c', 'sqlar.c', 'zipfile.c'],
windirent=['fileio.c']))
def install_custom_sqlite3(THIRD_PARTY, INTERNAL):
""" Begin install custom SQLite
Can be safely ignored even if it fails, however, system SQLite
imitations may prevent large database files with many columns
from working."""
if built_local():
return
PYSQLITE2 = INTERNAL + '/pysqlite2'
APSW = INTERNAL + '/apsw'
PYSQLITE = THIRD_PARTY + '/_pysqlite'
APSW_TP = THIRD_PARTY + '/_apsw'
SQLITE3 = THIRD_PARTY + '/sqlite3'
print("Installing custom SQLite 3 (pysqlite) ....")
install_env = os.environ.copy()
install_env["PYTHONPATH"] = INTERNAL + \
(':' + install_env["PYTHONPATH"] if "PYTHONPATH" in install_env else "")
copy_sqlite(SQLITE3, PYSQLITE)
copy_sqlite(SQLITE3, os.path.join(APSW_TP, 'src'), apsw=True)
rc = subprocess.Popen([
sys.executable,
PYSQLITE + '/setup.py',
'install',
'--install-lib=' + INTERNAL,
], cwd=PYSQLITE, env=install_env).wait()
if rc:
print("")
print("============================================================")
print("=========================WARNING============================")
print("============================================================")
print("It seems like building a custom version of SQLite on your")
print("machine has failed. This is fine, SuperSQLite will likely work")
print("just fine with the sytem version of SQLite for most use cases.")
print("However, if you are trying to load extremely high dimensional")
print("models > 999 dimensions, you may run in to SQLite limitations")
print("that can only be resolved by using the custom version of SQLite.")
print("To troubleshoot make sure you have appropriate build tools on")
print("your machine for building C programs like GCC and the standard")
print("library. Also make sure you have the python-dev development")
print("libraries and headers for building Python C extensions.")
print("If you need more help with this, please reach out to ")
print("opensource@plasticity.ai.")
print("============================================================")
print("============================================================")
print("")
else:
print("")
print("============================================================")
print("=========================SUCCESS============================")
print("============================================================")
print("Building a custom version of SQLite on your machine has")
print("succeeded.")
print("Listing internal...")
print(try_list_dir(INTERNAL))
print("Listing internal/pysqlite2...")
print(try_list_dir(PYSQLITE2))
print("============================================================")
print("============================================================")
print("")
print("Installing custom SQLite 3 (apsw) ....")
rc = subprocess.Popen([
sys.executable,
APSW_TP + '/setup.py',
'install',
'--install-lib=' + INTERNAL,
], cwd=APSW_TP, env=install_env).wait()
if rc:
print("")
print("============================================================")
print("=========================WARNING============================")
print("============================================================")
print("It seems like building a custom version of SQLite on your")
print("machine has failed. This is fine, SuperSQLite will likely work")
print("just fine with the sytem version of SQLite for most use cases.")
print("However, if you are trying to stream a remote model that")
print("can only be resolved by using the custom version of SQLite.")
print("To troubleshoot make sure you have appropriate build tools on")
print("your machine for building C programs like GCC and the standard")
print("library. Also make sure you have the python-dev development")
print("libraries and headers for building Python C extensions.")
print("If you need more help with this, please reach out to ")
print("opensource@plasticity.ai.")
print("============================================================")
print("============================================================")
print("")
else:
print("")
print("============================================================")
print("=========================SUCCESS============================")
print("============================================================")
print("Building a custom version of SQLite on your machine has")
print("succeeded.")
print("Listing internal...")
print(try_list_dir(INTERNAL))
print("Listing internal/apsw...")
print(try_list_dir(APSW))
print("============================================================")
print("============================================================")
print("")
if not(os.path.exists(APSW)):
print("Install-lib did not install APSW, installing from egg...")
for egg in glob(INTERNAL + "/apsw-*.egg"):
if (os.path.isfile(egg)):
print("Found an egg file, extracting...")
try:
zip_ref = zipfile.ZipFile(egg, 'r')
except BaseException:
print("Egg extraction error")
continue
zip_ref.extractall(APSW)
else:
print("Found an egg folder, renaming...")
os.rename(egg, APSW)
print("Renaming apsw.py to __init__.py")
os.rename(
os.path.join(
APSW, 'apsw.py'), os.path.join(
APSW, '__init__.py'))
def custom_compile(THIRD_PARTY, INTERNAL):
""" Compile resources this package needs """
install_custom_sqlite3(THIRD_PARTY, INTERNAL)
# Redirect output to a file
tee = open(
os.path.join(
tempfile.gettempdir(),
PACKAGE_SHORT_NAME +
'.install'),
'a+')
class TeeUnbuffered:
def __init__(self, stream):
self.stream = stream
self.errors = ""
def write(self, data):
self.stream.write(data)
self.stream.flush()
tee.write(data)
tee.flush()
def flush(self):
self.stream.flush()
tee.flush()
sys.stdout = TeeUnbuffered(sys.stdout)
sys.stderr = TeeUnbuffered(sys.stderr)
# Setup path constants
PROJ_PATH = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
THIRD_PARTY = PROJ_PATH + '/' + PACKAGE_NAME + '/third_party'
BUILD_PATH = PROJ_PATH + '/build'
BUILD_THIRD_PARTY = BUILD_PATH + '/lib/' + PACKAGE_NAME + '/third_party'
INTERNAL = THIRD_PARTY + '/internal'
BINARY_EXTENSIONS = (
'.so',
'.pyd',
'.dll',
'.o',
'.obj',
'.lib',
'.dylib',
'.a')
# Get the package version
__version__ = None
with open(os.path.join(PROJ_PATH, 'version.py')) as f:
exec(f.read())
# Setup remote wheel configurations
RM_WHEELHOUSE = 'https://s3.amazonaws.com/' + \
PACKAGE_SHORT_NAME + '.plasticity.ai/wheelhouse/'
TRIED_DOWNLOADING_WHEEL = os.path.join(
tempfile.gettempdir(),
PACKAGE_NAME +
'-' +
__version__ +
'-' +
hashlib.md5(PROJ_PATH.encode('utf-8')).hexdigest() +
'.whldownload'
)
INSTALLED_FROM_WHEEL = os.path.join(
tempfile.gettempdir(),
PACKAGE_NAME +
'-' +
__version__ +
'-' +
hashlib.md5(PROJ_PATH.encode('utf-8')).hexdigest() +
'.whlinstall'
)
BUILT_LOCAL = os.path.join(
tempfile.gettempdir(),
PACKAGE_NAME +
'-' +
__version__ +
'-' +
hashlib.md5(PROJ_PATH.encode('utf-8')).hexdigest() +
'.buildlocal'
)
def try_list_dir(d):
""" Return a list of files in a directory """
try:
return os.listdir(d)
except BaseException:
return []
def get_supported_wheels(package_name=PACKAGE_NAME, version=__version__):
"""Get supported wheel strings"""
def tuple_invalid(t):
return (
t[1] == 'none' or
'fat32' in t[2] or
'fat64' in t[2] or
'_universal' in t[2]
)
return ['-'.join((package_name, version) + t) + '.whl'
for t in pep425tags.get_supported() if not(tuple_invalid(t))]
def install_wheel(whl):
"""Installs a wheel file"""
whl_args = [
sys.executable,
'-m',
'pip',
'install',
'--ignore-installed',
]
rc = subprocess.Popen(whl_args + [whl]).wait()
if rc != 0:
try:
import site
if hasattr(site, 'getusersitepackages'):
site_packages = site.getusersitepackages()
print("Installing to user site packages...", site_packages)
rc = subprocess.Popen(whl_args + ["--user"] + [whl]).wait()
except ImportError:
pass
return rc
def skip_wheel():
""" Checks if a wheel install should be skipped """
return "SKIP_" + PACKAGE_SHORT_NAME.upper() + "_WHEEL" in os.environ
def installed_wheel():
"""Checks if a pre-compiled remote wheel was installed"""
return os.path.exists(INSTALLED_FROM_WHEEL)
def tried_downloading_wheel():
"""Checks if already tried downloading a wheel"""
return os.path.exists(TRIED_DOWNLOADING_WHEEL)
def built_local():
"""Checks if built out the project locally"""
return os.path.exists(BUILT_LOCAL)
def download_and_install_wheel():
"""Downloads and installs pre-compiled remote wheels"""
if skip_wheel():
return False
if installed_wheel():
return True
if tried_downloading_wheel():
return False
print("Downloading and installing wheel (if it exists)...")
tmpwhl_dir = tempfile.gettempdir()
for whl in get_supported_wheels():
exitcodes = []
whl_url = RM_WHEELHOUSE + whl
dl_path = os.path.join(tmpwhl_dir, whl)
try:
print("Trying...", whl_url)
urlretrieve(whl_url, dl_path)
except BaseException:
print("FAILED")
continue
extract_dir = os.path.join(
tempfile.gettempdir(), whl.replace(
'.whl', ''))
extract_dir = os.path.join(
tempfile.gettempdir(), whl.replace(
'.whl', ''))
try:
zip_ref = zipfile.ZipFile(dl_path, 'r')
except BaseException:
print("FAILED")
continue
zip_ref.extractall(extract_dir)
for ewhl in glob(extract_dir + "/*/req_wheels/*.whl"):
print("Installing requirement wheel: ", ewhl)
package_name = os.path.basename(ewhl).split('-')[0]
version = os.path.basename(ewhl).split('-')[1]
requirement = package_name + ">=" + version
print("Checking if requirement is met: ", requirement)
req_rc = subprocess.Popen([
sys.executable,
'-c',
"import importlib;"
"import pkg_resources;"
"pkg_resources.require('" + requirement + "');"
"importlib.import_module('" + package_name + "');"
]).wait()
if req_rc == 0:
print("Requirement met...skipping install of: ", package_name)
else:
print("Requirement not met...installing: ", package_name)
exitcodes.append(install_wheel(ewhl))
print("Installing wheel: ", dl_path)
exitcodes.append(install_wheel(dl_path))
zip_ref.extractall(PROJ_PATH)
zip_ref.close()
if len(exitcodes) > 0 and max(exitcodes) == 0 and min(exitcodes) == 0:
open(TRIED_DOWNLOADING_WHEEL, 'w+').close()
print("Done downloading and installing wheel")
return True
open(TRIED_DOWNLOADING_WHEEL, 'w+').close()
print("Done trying to download and install wheel (it didn't exist)")
return False
def parse_requirements(filename):
""" load requirements from a pip requirements file """
lineiter = (line.strip() for line in open(filename))
return [line for line in lineiter if line and not line.startswith("#")]
def build_req_wheels():
"""Builds requirement wheels"""
if built_local():
return
print("Building requirements wheels...")
# Get wheels from PyPI
rc = subprocess.Popen([
sys.executable,
'-m',
'pip',
'wheel',
'-r',
'requirements.txt',
'--wheel-dir=' + PACKAGE_NAME + '/req_wheels'
], cwd=PROJ_PATH).wait()
# Download wheels
for wheelhouse, package, versions in DOWNLOAD_REQ_WHEELS:
req_dl_success = False
for version in versions:
for whl in get_supported_wheels(package, version):
exitcodes = []
whl_url = wheelhouse + whl
sys.stdout.write("Trying to download... '" + whl_url + "'")
dl_path = os.path.join(PACKAGE_NAME + '/req_wheels', whl)
try:
urlretrieve(whl_url, dl_path)
zip_ref = zipfile.ZipFile(dl_path, 'r')
req_dl_success = True
sys.stdout.write(" ...SUCCESS\n")
except BaseException:
if os.path.exists(dl_path):
os.remove(dl_path)
sys.stdout.write(" ...FAIL\n")
continue
sys.stdout.flush()
# Try to get it from PyPI as last resort
if not req_dl_success:
rc2 = subprocess.Popen([
sys.executable,
'-m',
'pip',
'wheel',
package,
'--wheel-dir=' + PACKAGE_NAME + '/req_wheels'
], cwd=PROJ_PATH).wait()
if rc:
print("Failed to build requirements wheels!")
pass
def install_req_wheels():
"""Installs requirement wheels"""
print("Installing requirements wheels...")
for whl in glob(PACKAGE_NAME + '/req_wheels/*.whl'):
rc = install_wheel(whl)
print("Done installing requirements wheels")
def install_requirements():
"""Installs requirements.txt"""
print("Installing requirements...")
rc = subprocess.Popen([
sys.executable,
'-m',
'pip',
'install',
'-r',
'requirements.txt'
], cwd=PROJ_PATH).wait()
if rc:
print("Failed to install some requirements!")
print("Done installing requirements")
def get_site_packages():
""" Gets all site_packages paths """
try:
import site
if hasattr(site, 'getsitepackages'):
site_packages = site.getsitepackages()
else:
from distutils.sysconfig import get_python_lib
site_packages = [get_python_lib()]
if hasattr(site, 'getusersitepackages'):
site_packages = site_packages + [site.getusersitepackages()]
return site_packages
except BaseException:
return []
def source_for_module_with_pyinit(module, parent_module=''):
""" Create PyInit symbols for shared objects compiled with Python's
Extension()"""
source_path = os.path.join(BUILD_PATH, 'entrypoints')
try:
os.makedirs(source_path)
except BaseException:
pass
source_file = os.path.join(source_path, module + '.c')
with open(source_file, 'w+') as outfile:
outfile.write('''
void init''' + (parent_module + module) + '''(void) {} //Python 2.7
void PyInit_''' + (parent_module + module) + '''(void) {} //Python 3.5
''')
return os.path.relpath(source_file, PROJ_PATH)
def copy_custom_compile():
"""Copy the third party folders into site-packages under
PACKAGE_NAME/third_party/ and
./build/lib/PACKAGE_NAME/third_party/
for good measure"""
# Copy locally installed libraries
from distutils.dir_util import copy_tree
try:
site_packages = get_site_packages()
cp_from = THIRD_PARTY + '/'
for site_pack in site_packages:
for globbed in glob(site_pack + '/' + PACKAGE_NAME + '*/'):
try:
cp_to = (globbed + '/' + PACKAGE_NAME +
'/third_party/')
except IndexError as e:
print(
"Site Package: '" +
site_pack +
"' did not have " + PACKAGE_NAME)
continue
print("Copying from: ", cp_from, " --> to: ", cp_to)
copy_tree(cp_from, cp_to)
except Exception as e:
print("Error copying internal pysqlite folder to site packages:")
traceback.print_exc(e)
try:
cp_from = THIRD_PARTY + '/'
cp_to = BUILD_THIRD_PARTY + '/'
print("Copying from: ", cp_from, " --> to: ", cp_to)
copy_tree(cp_from, cp_to)
except Exception as e:
print("Error copying internal pysqlite folder to build folder:")
traceback.print_exc(e)
def delete_pip_files():
"""Delete random pip files"""
try:
from pip.utils.appdirs import user_cache_dir
except BaseException:
try:
from pip._internal.utils.appdirs import user_cache_dir
except BaseException:
return
for root, dirnames, filenames in os.walk(user_cache_dir('pip/wheels')):
for filename in fnmatch.filter(filenames, PACKAGE_NAME + '-*.whl'):
try:
whl = os.path.join(root, filename)
print("Deleting...", whl)
os.remove(whl)
except BaseException:
pass
try:
site_packages = get_site_packages()
for site_pack in site_packages:
for globbed in glob(site_pack + '/' + PACKAGE_NAME + '*/'):
try:
if globbed.endswith('.dist-info/'):
shutil.rmtree(globbed)
except BaseException:
pass
except BaseException:
pass
cmdclass = {}
try:
from wheel.bdist_wheel import bdist_wheel as bdist_wheel_
class CustomBdistWheelCommand(bdist_wheel_):
def run(self):
if not(download_and_install_wheel()):
custom_compile(THIRD_PARTY, INTERNAL)
build_req_wheels()
open(BUILT_LOCAL, 'w+').close()
print("Running wheel...")
bdist_wheel_.run(self)
print("Done running wheel")
copy_custom_compile()
cmdclass['bdist_wheel'] = CustomBdistWheelCommand
except ImportError as e:
pass
class CustomInstallCommand(install):
def run(self):
if not(download_and_install_wheel()):
custom_compile(THIRD_PARTY, INTERNAL)
install_req_wheels()
open(BUILT_LOCAL, 'w+').close()
print("Running install...")
p = Process(target=install.run, args=(self,))
p.start()
p.join()
print("Done running install")
if not(download_and_install_wheel()):
print("Running egg_install...")
p = Process(target=install.do_egg_install, args=(self,))
p.start()
p.join()
install_requirements()
print("Done running egg_install")
else:
print("Skipping egg_install")
copy_custom_compile()
def finalize_options(self):
install.finalize_options(self)
if self.distribution.has_ext_modules():
self.install_lib = self.install_platlib
class CustomBuildExtCommand(build_ext):
def run(self):
if not(download_and_install_wheel()):
print("Running build_ext...")
p = Process(target=build_ext.run, args=(self,))
p.start()
p.join()
print("Done running build_ext")
else:
print("Skipping build_ext...")
cmdclass['install'] = CustomInstallCommand
cmdclass['build_ext'] = CustomBuildExtCommand
class BinaryDistribution(Distribution):
def has_ext_modules(foo):
return True
MODULES = get_modules(THIRD_PARTY, INTERNAL, PROJ_PATH,
source_for_module_with_pyinit)
if __name__ == '__main__':
if 'CI_CC' in os.environ:
os.environ['CC'] = os.environ['CI_CC']
# Attempt to install from a remote pre-compiled wheel
if any([a in sys.argv for a in ['egg_info', 'install']]):
if download_and_install_wheel():
open(INSTALLED_FROM_WHEEL, 'w+').close()
# Only create requirements if not installing from a wheel
if any([a in sys.argv for a in ['bdist_wheel', 'sdist', 'egg_info']]):
# The wheel shouldn't have any reqs
# since it gets packaged with all of its req wheels
reqs = []
elif not any([a in sys.argv for a in ['-V']]):
reqs = parse_requirements('requirements.txt')
for wheelhouse, package, versions in DOWNLOAD_REQ_WHEELS:
if package not in reqs:
reqs.append(package)
print("Adding requirements: ", reqs)
else:
reqs = []
# Delete pip files
delete_pip_files()
setup(
name=PACKAGE_NAME,
packages=find_packages(
exclude=[
'tests',
'tests.*']),
version=__version__,
description='A supercharged SQLite library for Python.',
long_description="""
About
-----
A feature-packed Python package and for utilizing SQLite in Python by `Plasticity <https://www.plasticity.ai/>`_. It is intended to be a drop-in replacement to Python's built-in `SQLite API <https://docs.python.org/3/library/sqlite3.html>`_, but without any limitations. It offers unique features like remote streaming over HTTP and bundling of extensions like JSON, R-Trees (geospatial indexing), and Full Text Search.
Documentation
-------------
You can see the full documentation and README at the `GitLab repository <https://gitlab.com/Plasticity/supersqlite>`_ or the `GitHub repository <https://github.com/plasticityai/supersqlite>`_.
""",
author='Plasticity',
author_email='opensource@plasticity.ai',
url='https://gitlab.com/Plasticity/supersqlite',
keywords=[
'supersqlite',
'sqlite',
'sqlite3',
'apsw',
'pysqlite',
'sql',
'embedded',
'database',
'db',
'http',
'remote',
'stream',
'full',
'text',
'fulltext',
'full-text',
'json',
'lsm',
'blob',
'vfs',
'fts4',
'fts5'],
license='MIT',
include_package_data=True,
install_requires=reqs,
classifiers=[
"Development Status :: 5 - Production/Stable",
'Intended Audience :: Developers',
"Topic :: Software Development :: Libraries :: Python Modules",
"Operating System :: OS Independent",
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.0',
'Programming Language :: Python :: 3.7'],
cmdclass=cmdclass,
distclass=BinaryDistribution,
ext_modules=MODULES
)
# Delete pip files
delete_pip_files()
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/stoneqp/supersqlite.git
git@gitee.com:stoneqp/supersqlite.git
stoneqp
supersqlite
supersqlite
master

搜索帮助

23e8dbc6 1850385 7e0993f3 1850385