Added modular DAL, updated gluon imports to new structure
This commit is contained in:
1 parent
d73c668f2d
commit
5e5e649c28
43 files changed
+11577
-11686
No files matched your search
@@ -0,0 +1,307 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import decimal
|
||||
import re
|
||||
|
||||
from ._globals import LOGGER
|
||||
|
||||
|
||||
# verify presence of web2py modules
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
except:
|
||||
from gluon.contrib.ordereddict import OrderedDict
|
||||
|
||||
try:
|
||||
from gluon.utils import web2py_uuid
|
||||
except (ImportError, SystemError):
|
||||
import uuid
|
||||
def web2py_uuid(): return str(uuid.uuid4())
|
||||
|
||||
try:
|
||||
import portalocker
|
||||
have_portalocker = True
|
||||
except ImportError:
|
||||
portalocker = None
|
||||
have_portalocker = False
|
||||
|
||||
try:
|
||||
from gluon import serializers
|
||||
have_serializers = True
|
||||
simplejson = None
|
||||
except ImportError:
|
||||
serializers = None
|
||||
have_serializers = False
|
||||
try:
|
||||
import json as simplejson
|
||||
except ImportError:
|
||||
try:
|
||||
import gluon.contrib.simplejson as simplejson
|
||||
except ImportError:
|
||||
simplejson = None
|
||||
|
||||
|
||||
# list of drivers will be built on the fly
|
||||
# and lists only what is available
|
||||
DRIVERS = []
|
||||
|
||||
try:
|
||||
from new import classobj
|
||||
from google.appengine.ext import db as gae
|
||||
from google.appengine.ext import ndb
|
||||
from google.appengine.api import namespace_manager, rdbms
|
||||
from google.appengine.api.datastore_types import Key ### for belongs on ID
|
||||
from google.appengine.ext.db.polymodel import PolyModel
|
||||
from google.appengine.ext.ndb.polymodel import PolyModel as NDBPolyModel
|
||||
DRIVERS.append('google')
|
||||
except ImportError:
|
||||
classobj = None
|
||||
gae = None
|
||||
ndb = None
|
||||
namespace_manager = rdbms = None
|
||||
Key = None
|
||||
PolyModel = NDBPolyModel = None
|
||||
|
||||
if not 'google' in DRIVERS:
|
||||
|
||||
try:
|
||||
from pysqlite2 import dbapi2 as sqlite2
|
||||
DRIVERS.append('sqlite2')
|
||||
except ImportError:
|
||||
LOGGER.debug('no SQLite drivers pysqlite2.dbapi2')
|
||||
|
||||
try:
|
||||
from sqlite3 import dbapi2 as sqlite3
|
||||
DRIVERS.append('sqlite3')
|
||||
except ImportError:
|
||||
LOGGER.debug('no SQLite drivers sqlite3')
|
||||
|
||||
try:
|
||||
# first try contrib driver, then from site-packages (if installed)
|
||||
try:
|
||||
import gluon.contrib.pymysql as pymysql
|
||||
# monkeypatch pymysql because they havent fixed the bug:
|
||||
# https://github.com/petehunt/PyMySQL/issues/86
|
||||
pymysql.ESCAPE_REGEX = re.compile("'")
|
||||
pymysql.ESCAPE_MAP = {"'": "''"}
|
||||
# end monkeypatch
|
||||
except ImportError:
|
||||
import pymysql
|
||||
DRIVERS.append('pymysql')
|
||||
except ImportError:
|
||||
LOGGER.debug('no MySQL driver pymysql')
|
||||
|
||||
try:
|
||||
import MySQLdb
|
||||
DRIVERS.append('MySQLdb')
|
||||
except ImportError:
|
||||
LOGGER.debug('no MySQL driver MySQLDB')
|
||||
|
||||
try:
|
||||
import mysql.connector as mysqlconnector
|
||||
DRIVERS.append("mysqlconnector")
|
||||
except ImportError:
|
||||
LOGGER.debug("no driver mysql.connector")
|
||||
|
||||
try:
|
||||
import psycopg2
|
||||
from psycopg2.extensions import adapt as psycopg2_adapt
|
||||
DRIVERS.append('psycopg2')
|
||||
except ImportError:
|
||||
psycopg2_adapt = None
|
||||
LOGGER.debug('no PostgreSQL driver psycopg2')
|
||||
|
||||
try:
|
||||
# first try contrib driver, then from site-packages (if installed)
|
||||
try:
|
||||
import gluon.contrib.pg8000.dbapi as pg8000
|
||||
except ImportError:
|
||||
import pg8000.dbapi as pg8000
|
||||
DRIVERS.append('pg8000')
|
||||
except ImportError:
|
||||
LOGGER.debug('no PostgreSQL driver pg8000')
|
||||
|
||||
try:
|
||||
import cx_Oracle
|
||||
DRIVERS.append('cx_Oracle')
|
||||
except ImportError:
|
||||
cx_Oracle = None
|
||||
LOGGER.debug('no Oracle driver cx_Oracle')
|
||||
|
||||
try:
|
||||
try:
|
||||
import pyodbc
|
||||
except ImportError:
|
||||
try:
|
||||
import gluon.contrib.pypyodbc as pyodbc
|
||||
except Exception, e:
|
||||
raise ImportError(str(e))
|
||||
DRIVERS.append('pyodbc')
|
||||
#DRIVERS.append('DB2(pyodbc)')
|
||||
#DRIVERS.append('Teradata(pyodbc)')
|
||||
#DRIVERS.append('Ingres(pyodbc)')
|
||||
except ImportError:
|
||||
pyodbc = None
|
||||
LOGGER.debug('no MSSQL/DB2/Teradata/Ingres driver pyodbc')
|
||||
|
||||
try:
|
||||
import Sybase
|
||||
DRIVERS.append('Sybase')
|
||||
except ImportError:
|
||||
LOGGER.debug('no Sybase driver')
|
||||
|
||||
try:
|
||||
import kinterbasdb
|
||||
DRIVERS.append('kinterbasdb')
|
||||
#DRIVERS.append('Firebird(kinterbasdb)')
|
||||
except ImportError:
|
||||
LOGGER.debug('no Firebird/Interbase driver kinterbasdb')
|
||||
|
||||
try:
|
||||
import fdb
|
||||
DRIVERS.append('fdb')
|
||||
except ImportError:
|
||||
LOGGER.debug('no Firebird driver fdb')
|
||||
|
||||
try:
|
||||
import firebirdsql
|
||||
DRIVERS.append('firebirdsql')
|
||||
except ImportError:
|
||||
LOGGER.debug('no Firebird driver firebirdsql')
|
||||
|
||||
try:
|
||||
import informixdb
|
||||
DRIVERS.append('informixdb')
|
||||
LOGGER.warning('Informix support is experimental')
|
||||
except ImportError:
|
||||
LOGGER.debug('no Informix driver informixdb')
|
||||
|
||||
try:
|
||||
import sapdb
|
||||
DRIVERS.append('sapdb')
|
||||
LOGGER.warning('SAPDB support is experimental')
|
||||
except ImportError:
|
||||
LOGGER.debug('no SAP driver sapdb')
|
||||
|
||||
try:
|
||||
import cubriddb
|
||||
DRIVERS.append('cubriddb')
|
||||
LOGGER.warning('Cubrid support is experimental')
|
||||
except ImportError:
|
||||
LOGGER.debug('no Cubrid driver cubriddb')
|
||||
|
||||
try:
|
||||
from com.ziclix.python.sql import zxJDBC
|
||||
import java.sql
|
||||
# Try sqlite jdbc driver from http://www.zentus.com/sqlitejdbc/
|
||||
from org.sqlite import JDBC # required by java.sql; ensure we have it
|
||||
zxJDBC_sqlite = java.sql.DriverManager
|
||||
DRIVERS.append('zxJDBC')
|
||||
#DRIVERS.append('SQLite(zxJDBC)')
|
||||
LOGGER.warning('zxJDBC support is experimental')
|
||||
is_jdbc = True
|
||||
except ImportError:
|
||||
LOGGER.debug('no SQLite/PostgreSQL driver zxJDBC')
|
||||
is_jdbc = False
|
||||
|
||||
try:
|
||||
import couchdb
|
||||
DRIVERS.append('couchdb')
|
||||
except ImportError:
|
||||
couchdb = None
|
||||
LOGGER.debug('no Couchdb driver couchdb')
|
||||
|
||||
try:
|
||||
import pymongo
|
||||
DRIVERS.append('pymongo')
|
||||
except:
|
||||
LOGGER.debug('no MongoDB driver pymongo')
|
||||
|
||||
try:
|
||||
import imaplib
|
||||
DRIVERS.append('imaplib')
|
||||
except:
|
||||
LOGGER.debug('no IMAP driver imaplib')
|
||||
|
||||
GAEDecimalProperty = None
|
||||
NDBDecimalProperty = None
|
||||
else:
|
||||
is_jdbc = False
|
||||
|
||||
class GAEDecimalProperty(gae.Property):
|
||||
"""
|
||||
GAE decimal implementation
|
||||
"""
|
||||
data_type = decimal.Decimal
|
||||
|
||||
def __init__(self, precision, scale, **kwargs):
|
||||
super(GAEDecimalProperty, self).__init__(self, **kwargs)
|
||||
d = '1.'
|
||||
for x in range(scale):
|
||||
d += '0'
|
||||
self.round = decimal.Decimal(d)
|
||||
|
||||
def get_value_for_datastore(self, model_instance):
|
||||
value = super(GAEDecimalProperty, self)\
|
||||
.get_value_for_datastore(model_instance)
|
||||
if value is None or value == '':
|
||||
return None
|
||||
else:
|
||||
return str(value)
|
||||
|
||||
def make_value_from_datastore(self, value):
|
||||
if value is None or value == '':
|
||||
return None
|
||||
else:
|
||||
return decimal.Decimal(value).quantize(self.round)
|
||||
|
||||
def validate(self, value):
|
||||
value = super(GAEDecimalProperty, self).validate(value)
|
||||
if value is None or isinstance(value, decimal.Decimal):
|
||||
return value
|
||||
elif isinstance(value, basestring):
|
||||
return decimal.Decimal(value)
|
||||
raise gae.BadValueError("Property %s must be a Decimal or string."\
|
||||
% self.name)
|
||||
|
||||
#TODO Needs more testing
|
||||
class NDBDecimalProperty(ndb.StringProperty):
|
||||
"""
|
||||
NDB decimal implementation
|
||||
"""
|
||||
data_type = decimal.Decimal
|
||||
|
||||
def __init__(self, precision, scale, **kwargs):
|
||||
d = '1.'
|
||||
for x in range(scale):
|
||||
d += '0'
|
||||
self.round = decimal.Decimal(d)
|
||||
|
||||
def _to_base_type(self, value):
|
||||
if value is None or value == '':
|
||||
return None
|
||||
else:
|
||||
return str(value)
|
||||
|
||||
def _from_base_type(self, value):
|
||||
if value is None or value == '':
|
||||
return None
|
||||
else:
|
||||
return decimal.Decimal(value).quantize(self.round)
|
||||
|
||||
def _validate(self, value):
|
||||
if value is None or isinstance(value, decimal.Decimal):
|
||||
return value
|
||||
elif isinstance(value, basestring):
|
||||
return decimal.Decimal(value)
|
||||
raise TypeError("Property %s must be a Decimal or string."\
|
||||
% self._name)
|
||||
|
||||
psycopg2_adapt = None
|
||||
cx_Oracle = None
|
||||
pyodbc = None
|
||||
couchdb = None
|
||||
|
||||
|
||||
def get_driver(name):
|
||||
return globals().get(name)
|
||||
Reference in new issue
Block a user