Re: Uh-oh! Driver-specific exceptions are not abstracted....

Jacob Smullyan <[email protected]> Mon, 15 Aug 2005 23:25:23 -0400
Newsgroups gmane.comp.web.skunkweb
Message-ID <[email protected]>
On Mon, Aug 15, 2005 at 06:00:46PM -0700, Matthew Bogosian wrote:
> I just tried to violate an integrity constraint using PyDO with MySQL 
> and I received a MySQLdb.IntegrityError (which is an ancestor of 
> MySQLdb.MySQLError). For abstraction purposes, this is probably bad. I 
> should probably receive that error wrapped in a PyDOError. Better yet, 
> I should receive that error wrapped in the PyDO equivalent of an 
> integrity constraint violation, perferably as an ancestor of PyDOError 
> (e.g., PyDOIntegrityError).
> 
> If I'm writing code where I don't know (or I don't want to know) the 
> underlying implementation of the database, then I should only have to 
> worry about PyDOErrors. Code like this is worrysome:
> 
> try:
> 	myTableClass.new(unique_property = 'blah')
> except MySQLdb.IntegrityError:
> 	...
> except OraclesEquivalentIntegrityError:
> 	...
> except PostgreSQLsEquivalentIntegrityError:
> 	...
> 
> Instead, one should only have to write something like:
> 
> try:
> 	myTableClass.new(unique_property = 'blah')
> except pydo.exceptions.PyDOIntegrityError:

Cross-db abstractions have their place; generally I'm not keen on
them, but I'll resist the temptation to rant about that here.  The
particular problem you point out could occur, and can be solved much
more simply than by creating new exceptions, and wrapping all active
code to put them into play, all of which is overkill.

I would be inclined simply to import the mysql exceptions into my api
and refer to them as myapi.IntegrityError, etc., and then change them
if I changed dbs -- it would the least of the changes, probably! -- I
wouldn't attempt to write a single api with multiple db backends.  But
some people want to do that.

So, if you do, simply get a reference to the driver module that
corresponds to the dbi object and import the exceptions from it.  The
dbapi requires that all the exceptions have the same names, meaning,
and inheritance hierarchy, and drivers AFAICT are good about honoring
that.  In other words, do

  mod=getDriverMod(myAlias)
  Warning=getattr(mod, 'Warning')
  IntegrityError=getattr(mod, 'IntegrityError')

At the moment, getDriverMod wouldn't be as straightforward as one
might like; you need to get pydo.dbi._aliases[alias]['driver'] and
then map it to the correct module.  I'll add code so that it isn't
necessary to do anything so demeaning, but I'm not sure yet whether it
should be a separate function, a dbi method, or a "dbapi_module"
attribute of the dbi class/instance (which currently just has a
reference to the connect function).

Cheers,

js


-- 
Jacob Smullyan
signature.asc (application/pgp-signature, 189 B)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFDAVyjuqamFyFXXLIRAnIOAJsHnY/99RKH5smMPisnuetXVZuUQACfXfzu
A/+pxLib3UJIUKlrRew6Onw=
=cpbN
-----END PGP SIGNATURE-----