[sqlalchemy] MySQL Connector/Python support

2010-01-04 Thread geertjanvdk
Hello,

And best wishes for 2010! I am the maintainer, Geert Vanderkelen, of
MySQL Connector/Python at Sun Microsystems.

First, thanks for taking MySQL Connector/Python and putting it in as a
dialect in SQL Alchemy, great stuff already! This will be great for
other projects using SQLAlchemy. Very cool!

Few things:
* Could you change the dialect name from 'myconnpy' to
'mysqlconnector' or something like that. 'MySQL' should be first in
the name, as this is most 'official' thing the MySQL Team has done for
Python. Would be great. 'myconnpy' is just the short tag on LaunchPad.
* Checking the current trunk of SQLAlchemy, it's using a quite old
version of MySQL Connector/Python. We've done some development
releases lately, and there will be more. The bug mentioned, was fixed
though!

Maybe, if I'll find time, I'll check the code myself and do some work
there too.

I'm looking forward for ideas, and improvements for MySQL Connector/
Python to make the integration easier. If you guys have ideas, please
post them on LaunchPad.

Cheers,

Geert

--

You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.




[sqlalchemy] Re: MySQL Connector/Python support

2010-01-04 Thread geertjanvdk


On Jan 4, 5:29 pm, Michael Bayer mike...@zzzcomputing.com wrote:
..
  * Could you change the dialect name from 'myconnpy' to
  'mysqlconnector' or something like that. 'MySQL' should be first in
  the name, as this is most 'official' thing the MySQL Team has done for
  Python. Would be great. 'myconnpy' is just the short tag on LaunchPad.

 renamed to mysqlconnector in r6613.

Thanks so much for this! I think that name will make it more clear
what it is. There was additional myconnpy import in __init__.py,
which I corrected in the patch below.

  * Checking the current trunk of SQLAlchemy, it's using a quite old
  version of MySQL Connector/Python. We've done some development
  releases lately, and there will be more. The bug mentioned, was fixed
  though!

 There were two bugs that were being worked around, and for some reason the
 hyperlink in the source code were all for just one bug; additionally I
 can't seem to find any of those bugs on the launchpad site which doesn't
 seem to have any way to show resolved bugs, or they were removed, not
 really sure.   Anyway I've removed both workarounds in r6613 - using
 cursor.lastrowid now, using dbapi.paramstyle as is without forcing to
 positional.   Feel free to try out trunk and run the unit tests,
 specifying uri=mysql+mysqlconnector://user:n...@host/db !

Bugs should be kept on Launchpad, but lets see how we can make it work
with the development release of MySQL Connector/Python.

One change I did was _get_server_version_info(), see in patch
below.

I ran the tests, not sure how normal the number of errors is :)
(Using MySQL Connector/Python 0.1.2-dev)

shell nosetests --dburi=mysql+mysqlconnector://root:@localhost/
sqlalchemy
..
--
Ran 784 tests in 49.766s

FAILED (errors=499, failures=2)

Looking into a few.

-Geert


Index: lib/sqlalchemy/dialects/mysql/__init__.py
===
--- lib/sqlalchemy/dialects/mysql/__init__.py   (revision 6614)
+++ lib/sqlalchemy/dialects/mysql/__init__.py   (working copy)
@@ -1,4 +1,4 @@
-from sqlalchemy.dialects.mysql import base, mysqldb, oursql, pyodbc,
zxjdbc, myconnpy
+from sqlalchemy.dialects.mysql import base, mysqldb, oursql, pyodbc,
zxjdbc, mysqlconnector

 # default dialect
 base.dialect = mysqldb.dialect
Index: lib/sqlalchemy/dialects/mysql/mysqlconnector.py
===
--- lib/sqlalchemy/dialects/mysql/mysqlconnector.py (revision 6614)
+++ lib/sqlalchemy/dialects/mysql/mysqlconnector.py (working copy)
@@ -57,13 +57,7 @@

 def _get_server_version_info(self, connection):
 dbapi_con = connection.connection
-version = []
-r = re.compile('[.\-]')
-for n in r.split(dbapi_con.get_server_version()):
-try:
-version.append(int(n))
-except ValueError:
-version.append(n)
+version = dbapi_con.get_server_version()
 return tuple(version)

 def _detect_charset(self, connection):

--

You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.




Re: [sqlalchemy] Re: MySQL Connector/Python support

2010-01-04 Thread Michael Bayer
geertjanvdk wrote:

 Thanks so much for this! I think that name will make it more clear
 what it is. There was additional myconnpy import in __init__.py,
 which I corrected in the patch below.

oops, yeah , that is in r6615 thx

 One change I did was _get_server_version_info(), see in patch
 below.

that change is also in r6615.


 I ran the tests, not sure how normal the number of errors is :)
 (Using MySQL Connector/Python 0.1.2-dev)

 shell nosetests --dburi=mysql+mysqlconnector://root:@localhost/
 sqlalchemy
 ..
 --
 Ran 784 tests in 49.766s

 FAILED (errors=499, failures=2)

For MySQL dialects there should be no errors or failures - at most there
may be a handful of errors/failures which correspond to tests that should
be skipped for that DBAPI, although if you're getting one of those which
leads the database into an invalid state it may result in a cascade of
many failures.

It's more likely that the mysqlconnector dialect has some outdated
elements in it which need to be updated, or perhaps that there's some
DBAPI behavior not yet provided by mysqlconnector that SQLA is expecting. 
A log of tests running with MySQLdb as well as OurSQL is at
http://paste.pocoo.org/show/161970/

--

You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.




[sqlalchemy] Re: MySQL Connector/Python support

2010-01-04 Thread geertjanvdk

Thanks for the quick changes there!

On Jan 4, 7:45 pm, Michael Bayer mike...@zzzcomputing.com wrote:
..
 For MySQL dialects there should be no errors or failures - at most there
 may be a handful of errors/failures which correspond to tests that should
 be skipped for that DBAPI, although if you're getting one of those which
 leads the database into an invalid state it may result in a cascade of
 many failures.

OK, so I guess we got still a long way to go. :)
I ran tests with MySQLdb but ran in lots of failures, but I'm
concentrating on MySQL Connector/Python for now.

One thing I can't figure out is why tests are not cleaning
up or dropping tables. Works apparently good with MySQLdb, but
not with our Connector. Something for tomorrow on the train.

 It's more likely that the mysqlconnector dialect has some outdated
 elements in it which need to be updated, or perhaps that there's some
 DBAPI behavior not yet provided by mysqlconnector that SQLA is expecting.
 A log of tests running with MySQLdb as well as OurSQL is 
 athttp://paste.pocoo.org/show/161970/

Ah, attached another small patch, no need to parse, if you
got the errno right from the exception :)

-Geert

===
--- lib/sqlalchemy/dialects/mysql/mysqlconnector.py (revision 6615)
+++ lib/sqlalchemy/dialects/mysql/mysqlconnector.py (working copy)
@@ -66,11 +66,10 @@
 return connection.connection.get_characterset_info()

 def _extract_error_code(self, exception):
-m = re.compile(r\(.*\)\s+(\d+)).search(str(exception))
-c = m.group(1)
-if c:
-return int(c)
-else:
+try:
+if exception.errno  -1:
+return int(exception.errno)
+except:
 return None

--

You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.




[sqlalchemy] Re: new sqlalchemy user having problems to insert...

2010-01-04 Thread seth
Hi Mike,

Thank you very much for replying to my post. I really appreciate it.

I agree that the init of the classes may have something to do with the
problem.
Maybe the way we are defining the attributes does not allow to
SQLAlchemy table
wrappers to view the attributes' values?

What confuses me the most is that I am actually able to insert a row
using
sprint-python with the addxLPRVariable function  below.
Both approaches use the same variable classes.

The row with id=33 below was inserted using spring-python.
The row with id=32 below was inserted using SQLAlchemy.



mysql select * from variables where id =32;
+--+---+---+--+---
+--+
| id   | value | units | name | dependent |
independent_variable |
+--+---+---+--+---
+--+
| 0032 | 1 |   |  |  NULL
| NULL |
| 0033 | 1 | Hz| variable | 0
| NULL |
+--+---+---+--+---
+--+
2 rows in set (0.00 sec)


#--
#

This function writes to the database:

#--
#




def addxLPRVariable( self, xLPRVariable ):

Add an xLPRVariable to the database.
rowsAffected=self.database_template.execute( 
INSERT INTO variables
(id, name, units, value, dependent)
VALUES
(null, ?, ?, ?, ?)
, ( xLPRVariable.getName(), xLPRVariable.getUnits(),
xLPRVariable.getValue(), xLPRVariable.isDependent() ) )
self.connection_factory.commit()
logger.debug( Added %d rows%rowsAffected )
print Added %d%rowsAffected
return rowsAffected


#--
#

Here are the sql scripts

#--
#


create table variables
(
  id bigint(20) unsigned zerofill NOT NULL AUTO_INCREMENT COMMENT
'Primary key, sequence',
  value float NOT NULL COMMENT 'Initial value for variable',
  units varchar(45) NOT NULL COMMENT 'Common Si units of variable',
  name varchar(45) NOT NULL COMMENT 'Name of the variable',
  dependent boolean,
  independent_variable float COMMENT 'The independent variable x',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1  COMMENT='Maps to the
xLPRVariable Object';

create table dependence_variables
(
  id bigint(20) unsigned zerofill NOT NULL AUTO_INCREMENT COMMENT
'Primary key, sequence',
  variable_id bigint(20) unsigned zerofill COMMENT 'Foreign key to
dependency_variable table',
  interpolate boolean,
  dependent_function varchar(4000) COMMENT 'The dependent function',
  evaluate boolean,
  xname_units varchar(45),
  xname varchar(45),
  PRIMARY KEY (id),
  FOREIGN KEY (variable_id) REFERENCES variables(id)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1  COMMENT='Maps to the
dependency_variable object attribute';

create table data_set
(
  id bigint(20) unsigned zerofill NOT NULL AUTO_INCREMENT COMMENT
'Primary key, sequence',
  dependence_variable_id bigint(20) unsigned zerofill NOT NULL
COMMENT 'data_set will be grouped by data_set_ids',
  x float  NOT NULL COMMENT 'Value of x',
  y float  NOT NULL COMMENT 'Value of y',
  PRIMARY KEY (id),
  FOREIGN KEY (dependence_variable_id) REFERENCES dependence_variables
(id)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1  COMMENT='Maps to the
dependency_variable.data_set attribute';

#--
#

Here are the classes definition

#--
#
class xLPRVariable( VariableQuantity ):
'''
Defines a VariableUnitsAware object that may be a function of
another
independent variable x which is also a units-aware object

classdocs

args[0] = value:float
args[1] = units:str

kwargs['name'] = name:str
kwargs['dependenceVariable'] =
dependenceVariable:DependenceVariable

'''

def __init__( self, *args, **kwargs ):

'''
Constructor positional/required arguments:
value:float = initial value for variable
units:String = common SI units of variable

Constructor keyed/optional arguments:
name:String = name of variable
dependent:Boolean is variable dependent upon another SIAM
variable
dependenceVariable:DependenceVariable

'''

 
#===
# call the 

[sqlalchemy] Re: new sqlalchemy user having problems to insert...

2010-01-04 Thread seth
Here goes the variables' parent class


#===
# Variable quantities with units
# Written by Konrad Hinsen hin...@cnrs-orleans.fr
# with contributions from Greg Ward
# last revision: 2007-5-25
# Revised for SIAM-PFM by Paul Williams william...@ornl.gov
#
#===



class VariableQuantity( object ):
'''
Variable quantities with units.

This module provides a data type that represents a physical
quantity together with its units. It is possible to add and
subtract these quantities if the units are compatible, and
a quantity can be converted to another compatible unit.
Multiplication, subtraction, and raising to integer powers
is allowed without restriction, and the result will have
the correct unit. A quantity can be raised to a non-integer
power only if the result can be represented by integer powers
of the base units.

The values of physical constants are taken from the 1986
recommended values from CODATA. Other conversion factors
(e.g. for British units) come from various sources.

VariableQuantity instances allow addition, subtraction,
multiplication, and division with each other as well as
multiplication, division, and exponentiation with numbers.
Addition and subtraction check that the units of the two operands
are compatible and return the result in the units of the first
operand. A limited set of mathematical functions (from module
Numeric) is applicable as well:

  - sqrt: equivalent to exponentiation with 0.5.

  - sin, cos, tan: applicable only to objects whose unit is
compatible with 'rad'.

See the documentation of the VariableQuantities module for a list
of the available units.

Here is an example on usage:

 from PhysicalVariables import VariableQuantity as p  # short
hand
 distance1 = p('10 m')
 distance2 = p('10 km')
 total = distance1 + distance2
 total
VariableQuantity(10010.0,'m')
 total.convertToUnit('km')
 total.getValue()
10.01
 total.getUnitName()
'km'
 total = total.inBaseUnits()
 total
VariableQuantity(10010.0,'m')

 t = p(314159., 's')
 # convert to days, hours, minutes, and second:
 t2 = t.inUnitsOf('d','h','min','s')
 t2_print = ' '.join([str(i) for i in t2])
 t2_print
'3.0 d 15.0 h 15.0 min 59.0 s'

 e = p('2.7 Hartree*Nav')
 e.convertToUnit('kcal/mol')
 e
VariableQuantity(1694.2757596034764,'kcal/mol')
 e = e.inBaseUnits()
 str(e)
'7088849.77818 kg*m**2/s**2/mol'

 freeze = p('0 degC')
 freeze = freeze.inUnitsOf ('degF')
 str(freeze)
'32.0 degF'


'''


def __init__( self, *args ):
'''
There are two constructor calling patterns:

1. VariableQuantity(value, unit), where value is any
number
and unit is a string defining the unit

2. VariableQuantity(value_with_unit), where
value_with_unit
is a string that contains both the value and the unit,
i.e. '1.5 m/s'. This form is provided for more convenient
interactive use.

@param args: either (value, unit) or (value_with_unit,)
@type args: (number, C{str}) or (C{str},)
'''
if len( args )==2:
self.value=args[0]
self.unit=_findUnit( args[1] )
else:
s=string.strip( args[0] )
match=VariableQuantity._number.match( s )
if match is None:
raise TypeError( 'No number found' )
self.value=string.atof( match.group( 0 ) )
self.unit=_findUnit( s[len( match.group( 0 ) ):] )

_number=re.compile( '[+-]?[0-9]+(\\.[0-9]*)?([eE][+-]?[0-9]+)?' )

def __str__( self ):
return str( self.value )+' '+self.unit.name()

def __repr__( self ):
return ( self.__class__.__name__+'('+`self.value`+','+
`self.unit.name()`+')' )

def _sum( self, other, sign1, sign2 ):
if not isVariableQuantity( other ):
raise TypeError( 'Incompatible types' )
new_value=sign1*self.value+\
sign2*other.value*other.unit.conversionFactorTo
( self.unit )
return self.__class__( new_value, self.unit )

def __add__( self, other ):
return self._sum( other, 1, 1 )

__radd__=__add__

def __sub__( self, other ):
return self._sum( other, 1,-1 )

def __rsub__( self, other ):
return self._sum( other,-1, 1 )

def __cmp__( self, other ):
diff=self._sum( other, 1,-1 )
return cmp( diff.value, 0 )

def __mul__( self, other ):
if not isVariableQuantity( other ):
return self.__class__( self.value*other, self.unit )
value=self.value*other.value
unit=self.unit*other.unit
if unit.isDimensionless():
return value*unit.factor

Re: [sqlalchemy] Re: new sqlalchemy user having problems to insert...

2010-01-04 Thread Michael Bayer
seth wrote:
 Hi Mike,

 Thank you very much for replying to my post. I really appreciate it.

 I agree that the init of the classes may have something to do with the
 problem.
 Maybe the way we are defining the attributes does not allow to
 SQLAlchemy table
 wrappers to view the attributes' values?

hi Seth -

to be honest, I withheld saying anything earlier, but the very java-esque
style of code you have here is really not helping the performance of your
application or its readability.In Python, using explicit setters and
getters for all instance variables is unnecessary and adds palpable
overhead - since Python's method dispatch is nowheres near as efficient as
that of Java's. The famous rant on this topic is here: 
http://dirtsimple.org/2004/12/python-is-not-java.html  Also, the __name
style of naming, while it is part of pep8 and all, is becoming less and
less common these days as the implicit name mangling of the Python
interpreter leads to confusing results.

I don't see your mappings here but if in fact you're trying to map to
__name style attributes, its unlikely to work properly since SQLA doesn't
take into account the name mangling inherent in the usage of such names.  
It is a likely candidate for the issue you're having.









 What confuses me the most is that I am actually able to insert a row
 using
 sprint-python with the addxLPRVariable function  below.
 Both approaches use the same variable classes.

 The row with id=33 below was inserted using spring-python.
 The row with id=32 below was inserted using SQLAlchemy.



 mysql select * from variables where id =32;
 +--+---+---+--+---
 +--+
 | id   | value | units | name | dependent |
 independent_variable |
 +--+---+---+--+---
 +--+
 | 0032 | 1 |   |  |  NULL
 | NULL |
 | 0033 | 1 | Hz| variable | 0
 | NULL |
 +--+---+---+--+---
 +--+
 2 rows in set (0.00 sec)


 #--
 #

 This function writes to the database:

 #--
 #




 def addxLPRVariable( self, xLPRVariable ):

 Add an xLPRVariable to the database.
 rowsAffected=self.database_template.execute( 
 INSERT INTO variables
 (id, name, units, value, dependent)
 VALUES
 (null, ?, ?, ?, ?)
 , ( xLPRVariable.getName(), xLPRVariable.getUnits(),
 xLPRVariable.getValue(), xLPRVariable.isDependent() ) )
 self.connection_factory.commit()
 logger.debug( Added %d rows%rowsAffected )
 print Added %d%rowsAffected
 return rowsAffected


 #--
 #

 Here are the sql scripts

 #--
 #


 create table variables
 (
   id bigint(20) unsigned zerofill NOT NULL AUTO_INCREMENT COMMENT
 'Primary key, sequence',
   value float NOT NULL COMMENT 'Initial value for variable',
   units varchar(45) NOT NULL COMMENT 'Common Si units of variable',
   name varchar(45) NOT NULL COMMENT 'Name of the variable',
   dependent boolean,
   independent_variable float COMMENT 'The independent variable x',
   PRIMARY KEY (id)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1  COMMENT='Maps to the
 xLPRVariable Object';

 create table dependence_variables
 (
   id bigint(20) unsigned zerofill NOT NULL AUTO_INCREMENT COMMENT
 'Primary key, sequence',
   variable_id bigint(20) unsigned zerofill COMMENT 'Foreign key to
 dependency_variable table',
   interpolate boolean,
   dependent_function varchar(4000) COMMENT 'The dependent function',
   evaluate boolean,
   xname_units varchar(45),
   xname varchar(45),
   PRIMARY KEY (id),
   FOREIGN KEY (variable_id) REFERENCES variables(id)
   ON DELETE CASCADE
   ON UPDATE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1  COMMENT='Maps to the
 dependency_variable object attribute';

 create table data_set
 (
   id bigint(20) unsigned zerofill NOT NULL AUTO_INCREMENT COMMENT
 'Primary key, sequence',
   dependence_variable_id bigint(20) unsigned zerofill NOT NULL
 COMMENT 'data_set will be grouped by data_set_ids',
   x float  NOT NULL COMMENT 'Value of x',
   y float  NOT NULL COMMENT 'Value of y',
   PRIMARY KEY (id),
   FOREIGN KEY (dependence_variable_id) REFERENCES dependence_variables
 (id)
   ON DELETE CASCADE
   ON UPDATE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1  COMMENT='Maps to the
 dependency_variable.data_set attribute';