Honor CLASSPATH environment variable.

master
baztian 2013-10-12 20:09:33 +02:00
parent 77257eb619
commit 1f94731d35
3 changed files with 59 additions and 65 deletions

View File

@ -60,9 +60,12 @@ class. Then you can supply a single argument or a sequence of
arguments that are internally passed to the Java arguments that are internally passed to the Java
``DriverManager.getConnection`` method. Usually this is the JDBC ``DriverManager.getConnection`` method. Usually this is the JDBC
connection URL. See the Javadoc of ``DriverManager`` class for connection URL. See the Javadoc of ``DriverManager`` class for
details. As the next parameter you can optionally specify the details.
As the next parameter to ``connect`` you can optionally specify the
jar-Files of the driver if your classpath isn't set up sufficiently jar-Files of the driver if your classpath isn't set up sufficiently
yet. yet. The classpath set in ``CLASSPATH`` environment variable will be
honored. See the documentation of your Java runtime environment.
Here is an example: Here is an example:
@ -81,26 +84,12 @@ Here is an example:
>>> curs.fetchall() >>> curs.fetchall()
[(1, u'John')] [(1, u'John')]
You probably have to configure Jython or JPype to actually be able to If you're having trouble getting this work check if your ``JAVA_HOME``
access the database driver's jar files. If I want to connect to a HSQL environmentvariable is set correctly. For example I have to set it on
in memory database on my Ubuntu machine I'm starting Python by running :: my Ubuntu machine like this ::
$ JAVA_HOME=/usr/lib/jvm/java-6-openjdk python $ JAVA_HOME=/usr/lib/jvm/java-6-openjdk python
Now I have to configure JPype
>>> import jpype
>>> jar = r'/path/to/my/driver/hsqldb.jar'
>>> args='-Djava.class.path=%s' % jar
>>> jvm_path = jpype.getDefaultJVMPath()
>>> jpype.startJVM(jvm_path, args)
or in Jython I have to
>>> jar = '/path/to/my/driver/hsqldb.jar'
>>> import sys
>>> sys.path.append(jar)
Supported databases Supported databases
=================== ===================
@ -169,6 +158,8 @@ Changelog
- Set ``.rowcount`` properly. - Set ``.rowcount`` properly.
- Honor ``CLASSPATH`` if used in JPype mode.
- 0.1.3 - 0.1.3
- Fixed DB-API_ violation: Use ``curs.execute('foo ?', (bar, baz))`` - Fixed DB-API_ violation: Use ``curs.execute('foo ?', (bar, baz))``

View File

@ -19,6 +19,7 @@
import datetime import datetime
import exceptions import exceptions
import glob
import os import os
import time import time
import re import re
@ -84,9 +85,13 @@ def _jdbc_connect_jpype(jclassname, jars, libs, *driver_args):
import jpype import jpype
if not jpype.isJVMStarted(): if not jpype.isJVMStarted():
args = [] args = []
class_path = []
if jars: if jars:
class_path = os.path.pathsep.join(jars) class_path.extend(jars)
args.append('-Djava.class.path=%s' % class_path) class_path.extend(_get_classpath())
if class_path:
args.append('-Djava.class.path=%s' %
os.path.pathsep.join(class_path))
if libs: if libs:
# path to shared libraries # path to shared libraries
libs_path = os.path.pathsep.join(libs) libs_path = os.path.pathsep.join(libs)
@ -111,6 +116,25 @@ def _jdbc_connect_jpype(jclassname, jars, libs, *driver_args):
jpype.JClass(jclassname) jpype.JClass(jclassname)
return jpype.java.sql.DriverManager.getConnection(*driver_args) return jpype.java.sql.DriverManager.getConnection(*driver_args)
def _get_classpath():
"""Extract CLASSPATH from system environment as JPype doesn't seem
to respect that variable.
"""
try:
orig_cp = os.environ['CLASSPATH']
except KeyError:
return []
expanded_cp = []
for i in orig_cp.split(os.path.pathsep):
expanded_cp.extend(_jar_glob(i))
return expanded_cp
def _jar_glob(item):
if item.endswith('*'):
return glob.glob('%s.[jJ][aA][rR]' % item)
else:
return [item]
def _prepare_jpype(): def _prepare_jpype():
global _jdbc_connect global _jdbc_connect
_jdbc_connect = _jdbc_connect_jpype _jdbc_connect = _jdbc_connect_jpype

View File

@ -25,42 +25,11 @@ import threading
import unittest2 as unittest import unittest2 as unittest
this_dir = os.path.dirname(os.path.abspath(__file__)) _THIS_DIR = os.path.dirname(os.path.abspath(__file__))
def jar(jar_file):
return os.path.abspath(os.path.join(this_dir, '..', '..', 'build', 'lib',
jar_file))
_DRIVERS = {
#http://bitbucket.org/xerial/sqlite-jdbc
'sqlite_xerial': ( 'org.sqlite.JDBC', 'jdbc:sqlite::memory:',
jar('sqlite-jdbc-3.7.2.jar'), None),
# http://hsqldb.org/
'hsqldb': ( 'org.hsqldb.jdbcDriver', ['jdbc:hsqldb:mem:.', 'SA', ''],
jar('hsqldb.jar'), None),
'db2jcc': ( 'com.ibm.db2.jcc.DB2Driver',
['jdbc:db2://4.100.73.81:50000/db2t', 'user', 'passwd'],
jar('jarfile.jar'), None),
# driver from http://www.ch-werner.de/javasqlite/ seems to be
# crap as it returns decimal values as VARCHAR type
'sqlite_werner': ( 'SQLite.JDBCDriver', 'jdbc:sqlite:/:memory:',
jar('sqlite.jar'), None),
# Oracle Thin Driver
'oracle_thin': ('oracle.jdbc.OracleDriver',
['jdbc:oracle:thin:@//hh-cluster-scan:1521/HH_TPP',
'user', 'passwd'],
jar('jarfile.jar'), None)
}
def is_jython(): def is_jython():
return sys.platform.lower().startswith('java') return sys.platform.lower().startswith('java')
def driver_name():
try:
return os.environ['INTEGRATION_TEST_DRIVER']
except KeyError:
return 'sqlite_xerial'
class IntegrationTest(unittest.TestCase): class IntegrationTest(unittest.TestCase):
def sql_file(self, filename): def sql_file(self, filename):
@ -89,27 +58,37 @@ class IntegrationTest(unittest.TestCase):
return sqlite3, sqlite3.connect(':memory:') return sqlite3, sqlite3.connect(':memory:')
def connect(self): def connect(self):
driver = driver_name() #http://bitbucket.org/xerial/sqlite-jdbc
driver_class, driver_args, driver_jars, driver_libs = _DRIVERS[driver] # sqlite-jdbc-3.7.2.jar
conn = jaydebeapi.connect(driver_class, driver_args, driver_jars, driver, driver_args = 'org.sqlite.JDBC', 'jdbc:sqlite::memory:'
driver_libs) # http://hsqldb.org/
# hsqldb.jar
#driver, driver_args = 'org.hsqldb.jdbcDriver', ['jdbc:hsqldb:mem:.',
# 'SA', '']
# db2jcc
# driver, driver_args = 'com.ibm.db2.jcc.DB2Driver', \
# ['jdbc:db2://4.100.73.81:50000/db2t', 'user', 'passwd']
# driver from http://www.ch-werner.de/javasqlite/ seems to be
# crap as it returns decimal values as VARCHAR type
# sqlite.jar
# driver, driver_args = 'SQLite.JDBCDriver', 'jdbc:sqlite:/:memory:'
# Oracle Thin Driver
# driver, driver_args = 'oracle.jdbc.OracleDriver', \
# ['jdbc:oracle:thin:@//hh-cluster-scan:1521/HH_TPP',
# 'user', 'passwd']
conn = jaydebeapi.connect(driver, driver_args)
return jaydebeapi, conn return jaydebeapi, conn
def _driver_specific_sql(self, data_file): def _driver_specific_sql(self, data_file):
driver = driver_name()
sql_file = os.path.join(this_dir, 'data', '%s_%s.sql' % (data_file,
driver))
if os.path.exists(sql_file): if os.path.exists(sql_file):
return sql_file return sql_file
else: else:
return os.path.join(this_dir, 'data', '%s.sql' % data_file) return os.path.join(_THIS_DIR, 'data', '%s.sql' % data_file)
def setUp(self): def setUp(self):
(self.dbapi, self.conn) = self.connect() (self.dbapi, self.conn) = self.connect()
create_sql = self._driver_specific_sql('create') self.sql_file(os.path.join(_THIS_DIR, 'data', 'create.sql'))
self.sql_file(create_sql) self.sql_file(os.path.join(_THIS_DIR, 'data', 'insert.sql'))
insert_sql = self._driver_specific_sql('insert')
self.sql_file(insert_sql)
def tearDown(self): def tearDown(self):
cursor = self.conn.cursor() cursor = self.conn.cursor()