Permalink
Browse files

BioSQL support in Jython

  • Loading branch information...
1 parent 3765a18 commit d9994a432b2e929465b1ef64cbe7fd0ebfefa3b7 @tiagoantao tiagoantao committed Feb 19, 2013
Showing with 90 additions and 26 deletions.
  1. +31 −4 BioSQL/BioSeqDatabase.py
  2. +12 −2 BioSQL/DBUtils.py
  3. +2 −2 BioSQL/Loader.py
  4. +4 −0 NEWS
  5. +40 −17 Tests/common_BioSQL.py
  6. +1 −1 Tests/test_BioSQL_psycopg2.py
View
@@ -1,6 +1,7 @@
# Copyright 2002 by Andrew Dalke. All rights reserved.
# Revisions 2007-2009 copyright by Peter Cock. All rights reserved.
# Revisions 2009 copyright by Cymon J. Cox. All rights reserved.
+# Revisions 2013 copyright by Tiago Antao. All rights reserved.
# This code is part of the Biopython distribution and governed by its
# license. Please see the LICENSE file that should have been included
# as part of this package.
@@ -12,6 +13,8 @@
This provides interfaces for loading biological objects from a relational
database, and is compatible with the BioSQL standards.
"""
+import os
+
from Bio import BiopythonDeprecationWarning
import BioSeq
@@ -43,12 +46,23 @@ def open_database(driver="MySQLdb", **kwargs):
raise ValueError("Using BioSQL with psycopg (version one) is no "
"longer supported. Use psycopg2 instead.")
- module = __import__(driver)
+ if os.name == "java":
+ from com.ziclix.python.sql import zxJDBC
+ module = zxJDBC
+ if driver in ["MySQLdb"]:
+ jdbc_driver = "com.mysql.jdbc.Driver"
+ url_pref = "jdbc:mysql://" + kwargs["host"] + "/"
+ elif driver in ["psycopg2"]:
+ jdbc_driver = "org.postgresql.Driver"
+ url_pref = "jdbc:postgresql://" + kwargs["host"] + "/"
+
+ else:
+ module = __import__(driver)
connect = getattr(module, "connect")
# Different drivers use different keywords...
kw = kwargs.copy()
- if driver == "MySQLdb":
+ if driver == "MySQLdb" and os.name != "java":
if "database" in kw:
kw["db"] = kw["database"]
del kw["database"]
@@ -66,7 +80,15 @@ def open_database(driver="MySQLdb", **kwargs):
if driver in ["psycopg2", "pgdb"] and not kw.get("database"):
kw["database"] = "template1"
# SQLite connect takes the database name as input
- if driver in ["sqlite3"]:
+ if os.name == "java":
+ if driver in ["MySQLdb"]:
+ conn = connect(url_pref + kw.get("database", "mysql"),
+ kw["user"], kw["password"], jdbc_driver)
+ elif driver in ["psycopg2"]:
+ conn = connect(url_pref + kw.get("database", "postgresql") +
+ "?stringtype=unspecified",
+ kw["user"], kw["password"], jdbc_driver)
+ elif driver in ["sqlite3"]:
conn = connect(kw["database"])
else:
try:
@@ -83,7 +105,10 @@ def open_database(driver="MySQLdb", **kwargs):
dsn = ' '.join(['='.join(i) for i in kw.items()])
conn = connect(dsn)
- server = DBServer(conn, module)
+ if os.name == "java":
+ server = DBServer(conn, module, driver)
+ else:
+ server = DBServer(conn, module)
# TODO - Remove the following once BioSQL Bug 2839 is fixed.
# Test for RULES in PostgreSQL schema, see also Bug 2833.
@@ -411,6 +436,8 @@ def execute_one(self, sql, args=None):
def execute(self, sql, args=None):
"""Just execute an sql command.
"""
+ if os.name == "java":
+ sql = sql.replace("%s", "?")
self.dbutils.execute(self.cursor, sql, args)
def get_subseq_as_string(self, seqid, start, end):
View
@@ -1,12 +1,14 @@
# Copyright 2002 by Andrew Dalke. All rights reserved.
# Revisions 2007-2010 copyright by Peter Cock. All rights reserved.
# Revisions 2009 copyright by Brad Chapman. All rights reserved.
+# Revisions 2013 copyright by Tiago Antao. All rights reserved.
# This code is part of the Biopython distribution and governed by its
# license. Please see the LICENSE file that should have been included
# as part of this package.
#
# Note that BioSQL (including the database schema and scripts) is
# available and licensed separately. Please consult www.biosql.org
+import os
_dbutils = {}
@@ -53,6 +55,8 @@ def execute(self, cursor, sql, args=None):
class Mysql_dbutils(Generic_dbutils):
"""Custom database utilities for MySQL."""
def last_id(self, cursor, table):
+ if os.name == "java":
+ return Generic_dbutils.last_id(self, cursor, table)
try:
#This worked on older versions of MySQL
return cursor.insert_id()
@@ -86,9 +90,15 @@ class Psycopg2_dbutils(_PostgreSQL_dbutils):
"""Custom database utilities for Psycopg2 (PostgreSQL)."""
def autocommit(self, conn, y=True):
if y:
- conn.set_isolation_level(0)
+ if os.name == "java":
+ conn.autocommit = 1
+ else:
+ conn.set_isolation_level(0)
else:
- conn.set_isolation_level(1)
+ if os.name == "java":
+ conn.autocommit = 0
+ else:
+ conn.set_isolation_level(1)
_dbutils["psycopg2"] = Psycopg2_dbutils
View
@@ -355,7 +355,7 @@ def _get_taxon_id_from_ncbi_taxon_id(self, ncbi_taxon_id,
taxon_id = self.adaptor.execute_and_fetch_col0(
"SELECT taxon_id FROM taxon WHERE ncbi_taxon_id = %s",
- (ncbi_taxon_id,))
+ (int(ncbi_taxon_id),))
if taxon_id:
#Good, we have mapped the NCBI taxid to a taxon table entry
return taxon_id[0]
@@ -832,7 +832,7 @@ def _insert_location(self, location, rank, seqfeature_id):
if location.ref:
# sub_feature remote locations when they are in the same db as the current
# record do not have a value for ref_db, which the SeqFeature object
- # stores as None. BioSQL schema requires a varchar and is not NULL
+ # stores as None. BioSQL schema requires a varchar and is not NULL
dbxref_id = self._get_dbxref_id(location.ref_db or "", location.ref)
else:
dbxref_id = None
View
4 NEWS
@@ -26,6 +26,9 @@ formats NeXML and CDAO. The Newick parser is also significantly faster, and can
now optionally extract bootstrap values from the Newick comment field (like
Molphy and Archaeopteryx do).
+The BioSQL module is now supported in Jython. MySQL and PostgreSQL databases
+can be used. The relevant JDBC driver should be available in the CLASSPATH.
+
Additionally there have been other minor bug fixes and more unit tests.
Many thanks to the Biopython developers and community for making this release
@@ -34,6 +37,7 @@ possible, especially the following contributors:
Ben Morris (first contribution)
Peter Cock
Petra Kubincová (first contribution)
+Tiago Antao
===================================================================
View
@@ -5,6 +5,7 @@
"""
# standard library
import os
+import platform
import unittest
from StringIO import StringIO
@@ -31,10 +32,14 @@
raise RuntimeError("Call this via test_BioSQL_*.py not directly")
global DBDRIVER, DBTYPE, DBHOST, DBUSER, DBPASSWD, TESTDB, DBSCHEMA, SQL_FILE
+global SYSTEM
+
+SYSTEM = platform.system()
def check_config(dbdriver, dbtype, dbhost, dbuser, dbpasswd, testdb):
- global DBDRIVER, DBTYPE, DBHOST, DBUSER, DBPASSWD, TESTDB, DBSCHEMA, SQL_FILE
+ global DBDRIVER, DBTYPE, DBHOST, DBUSER, DBPASSWD, TESTDB, DBSCHEMA
+ global SYSTEM, SQL_FILE
DBDRIVER = dbdriver
DBTYPE = dbtype
DBHOST = dbhost
@@ -43,19 +48,29 @@ def check_config(dbdriver, dbtype, dbhost, dbuser, dbpasswd, testdb):
TESTDB = testdb
#Check the database driver is installed:
- try:
- __import__(DBDRIVER)
- except ImportError:
- message = "Install %s if you want to use %s with BioSQL " % (DBDRIVER, DBTYPE)
- raise MissingExternalDependencyError(message)
+ if SYSTEM == "Java":
+ try:
+ if DBDRIVER in ["MySQLdb"]:
+ import com.mysql.jdbc.Driver
+ elif DBDRIVER in ["psycopg2"]:
+ import org.postgresql.Driver
+ except ImportError:
+ message = "Install the JDBC driver for %s to use BioSQL " % DBTYPE
+ raise MissingExternalDependencyError(message)
+ else:
+ try:
+ __import__(DBDRIVER)
+ except ImportError:
+ message = "Install %s if you want to use %s with BioSQL " % (DBDRIVER, DBTYPE)
+ raise MissingExternalDependencyError(message)
try:
if DBDRIVER in ["sqlite3"]:
- server = BioSeqDatabase.open_database(driver = DBDRIVER, db = TESTDB)
+ server = BioSeqDatabase.open_database(driver=DBDRIVER, db=TESTDB)
else:
- server = BioSeqDatabase.open_database(driver = DBDRIVER,
- user = DBUSER, passwd = DBPASSWD,
- host = DBHOST)
+ server = BioSeqDatabase.open_database(driver=DBDRIVER,
+ user=DBUSER, passwd=DBPASSWD,
+ host=DBHOST)
server.close()
del server
except Exception, e:
@@ -101,6 +116,7 @@ def _do_db_create():
sql = r"DROP DATABASE " + TESTDB
server.adaptor.cursor.execute(sql, ())
except (server.module.OperationalError,
+ server.module.Error,
server.module.DatabaseError), e: # the database doesn't exist
pass
except (server.module.IntegrityError,
@@ -456,6 +472,7 @@ def test_duplicate_load(self):
#Note we don't do a specific exception handler because the
#exception class will depend on which DB back end is in use.
self.assertTrue(err.__class__.__name__ in ["IntegrityError",
+ "AttributeError",
"OperationalError"],
err.__class__.__name__)
return
@@ -470,7 +487,9 @@ def test_duplicate_load2(self):
count = self.db.load([record])
except Exception, err:
#Good!
- self.assertEqual("IntegrityError", err.__class__.__name__)
+ self.assertTrue(err.__class__.__name__ in ["IntegrityError",
+ "AttributeError"],
+ err.__class__.__name__)
return
raise Exception("Should have failed! Loaded %i records" % count)
@@ -482,7 +501,9 @@ def test_duplicate_id_load(self):
count = self.db.load([record1, record2])
except Exception, err:
#Good!
- self.assertEqual("IntegrityError", err.__class__.__name__)
+ self.assertTrue(err.__class__.__name__ in ["IntegrityError",
+ "AttributeError"],
+ err.__class__.__name__)
return
raise Exception("Should have failed! Loaded %i records" % count)
@@ -678,7 +699,9 @@ def test_reload(self):
count = self.db.load([record])
except Exception, err:
#Good!
- self.assertEqual("IntegrityError", err.__class__.__name__)
+ self.assertTrue(err.__class__.__name__ in ["IntegrityError",
+ "AttributeError"],
+ err.__class__.__name__)
return
raise Exception("Should have failed! Loaded %i records" % count)
@@ -760,10 +783,10 @@ class AutoSeqIOTests(unittest.TestCase):
def setUp(self):
"""Connect to the database."""
db_name = "biosql-test-seqio"
- server = BioSeqDatabase.open_database(driver = DBDRIVER,
- user = DBUSER,
- passwd = DBPASSWD,
- host = DBHOST, db = TESTDB)
+ server = BioSeqDatabase.open_database(driver=DBDRIVER,
+ user=DBUSER,
+ passwd=DBPASSWD,
+ host=DBHOST, db=TESTDB)
self.server = server
if db_name not in server.keys():
self.db = server.new_database(db_name)
@@ -3,7 +3,7 @@
# license. Please see the LICENSE file that should have been included
# as part of this package.
-"""Run BioSQL tests using SQLite"""
+"""Run BioSQL tests using PostgreSQL"""
from Bio import MissingExternalDependencyError
from BioSQL import BioSeqDatabase

0 comments on commit d9994a4

Please sign in to comment.