diff --git a/README.rst b/README.rst index e9e1d7f..346d8e8 100644 --- a/README.rst +++ b/README.rst @@ -60,9 +60,12 @@ class. Then you can supply a single argument or a sequence of arguments that are internally passed to the Java ``DriverManager.getConnection`` method. Usually this is the JDBC 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 -yet. +yet. The classpath set in ``CLASSPATH`` environment variable will be +honored. See the documentation of your Java runtime environment. Here is an example: @@ -81,26 +84,12 @@ Here is an example: >>> curs.fetchall() [(1, u'John')] -You probably have to configure Jython or JPype to actually be able to -access the database driver's jar files. If I want to connect to a HSQL -in memory database on my Ubuntu machine I'm starting Python by running :: +If you're having trouble getting this work check if your ``JAVA_HOME`` +environmentvariable is set correctly. For example I have to set it on +my Ubuntu machine like this :: $ 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 =================== @@ -169,6 +158,8 @@ Changelog - Set ``.rowcount`` properly. + - Honor ``CLASSPATH`` if used in JPype mode. + - 0.1.3 - Fixed DB-API_ violation: Use ``curs.execute('foo ?', (bar, baz))`` diff --git a/src/jaydebeapi/dbapi2.py b/src/jaydebeapi/dbapi2.py index 4140681..c822ae9 100644 --- a/src/jaydebeapi/dbapi2.py +++ b/src/jaydebeapi/dbapi2.py @@ -19,6 +19,7 @@ import datetime import exceptions +import glob import os import time import re @@ -84,9 +85,13 @@ def _jdbc_connect_jpype(jclassname, jars, libs, *driver_args): import jpype if not jpype.isJVMStarted(): args = [] + class_path = [] if jars: - class_path = os.path.pathsep.join(jars) - args.append('-Djava.class.path=%s' % class_path) + class_path.extend(jars) + class_path.extend(_get_classpath()) + if class_path: + args.append('-Djava.class.path=%s' % + os.path.pathsep.join(class_path)) if libs: # path to shared libraries libs_path = os.path.pathsep.join(libs) @@ -111,6 +116,25 @@ def _jdbc_connect_jpype(jclassname, jars, libs, *driver_args): jpype.JClass(jclassname) 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(): global _jdbc_connect _jdbc_connect = _jdbc_connect_jpype diff --git a/src/test/test_integration.py b/src/test/test_integration.py index 3f8cc0a..e6cca66 100644 --- a/src/test/test_integration.py +++ b/src/test/test_integration.py @@ -25,42 +25,11 @@ import threading import unittest2 as unittest -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) - } +_THIS_DIR = os.path.dirname(os.path.abspath(__file__)) def is_jython(): 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): def sql_file(self, filename): @@ -89,27 +58,37 @@ class IntegrationTest(unittest.TestCase): return sqlite3, sqlite3.connect(':memory:') def connect(self): - driver = driver_name() - driver_class, driver_args, driver_jars, driver_libs = _DRIVERS[driver] - conn = jaydebeapi.connect(driver_class, driver_args, driver_jars, - driver_libs) + #http://bitbucket.org/xerial/sqlite-jdbc + # sqlite-jdbc-3.7.2.jar + driver, driver_args = 'org.sqlite.JDBC', 'jdbc:sqlite::memory:' + # 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 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): return sql_file 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): (self.dbapi, self.conn) = self.connect() - create_sql = self._driver_specific_sql('create') - self.sql_file(create_sql) - insert_sql = self._driver_specific_sql('insert') - self.sql_file(insert_sql) + self.sql_file(os.path.join(_THIS_DIR, 'data', 'create.sql')) + self.sql_file(os.path.join(_THIS_DIR, 'data', 'insert.sql')) def tearDown(self): cursor = self.conn.cursor()