[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-15 Thread sdobrev

On Wednesday 15 August 2007 04:26:31 Michael Bayer wrote:
 On Aug 14, 2007, at 4:35 PM, Michael Bayer wrote:
  On Aug 14, 2007, at 12:38 PM, svilen wrote:
  ---
  orm.attribute
AttributeManager.init_attr():
  the saving this one eventualy does is too small, compared to
  a property call of ._state.
 
  i havent benched this in a while but my recollection is that the
  AttributeError raise is *much* slower than pre-calling this
  method. a single function call is always faster than an exception
  throw.
 
  however, i see that the exception throw is being suppressed also
  with a hasattr() being called every timeim not sure why thats
  that way now so i might change it back to throwing
  AttributeError.

 the results are in, running test/prof/masseagerload.py.  this test
 is very heavy on creating new instances from mapper rows, which is
 where the initialization of _state comes in.

 no init_attr(), detect missing with AttributeError
 Profiled target 'masseagerload', wall time: 0.59 seconds
 Profile report for target 'masseagerload' (masseagerload.prof)
 57039 function calls (55962 primitive calls) in 0.489 CPU seconds

 init_attr(), detect missing with AttributeError
 Profiled target 'masseagerload', wall time: 0.53 seconds
 57549 function calls (56472 primitive calls) in 0.426 CPU seconds

 init_attr(), detect missing with hasattr
 Profiled target 'masseagerload', wall time: 0.56 seconds
 57549 function calls (56472 primitive calls) in 0.431 CPU seconds

 no init_attr(), detect missing with hasattr
 Profiled target 'masseagerload', wall time: 0.49 seconds
 57039 function calls (55962 primitive calls) in 0.390 CPU seconds

 im not exactly sure why the hasattr() call, being present and
 then removed, doesnt change the number of function calls.  anyway, 
 the times vary a little bit but the hasattr call, even though its
 called many more times than the AttributeError gets raised, is
 slightly faster than raising AttributeError.  so no AttributeError,
 and I like getting rid of init_attr() very much so its out in
 r3313.

heh. 

First, the init_attr as it was, has never worked - it sets up a 
private __sa_attr_state, while what is used is plain non-private 
_sa_attr_state attribute (note starting underscores).

Second, i went to r3312, let init_attr() set a _state as plain dict 
and removed _state as property. The difference plain-dict/property 
(in favor of plain dict) is like 2-3%.

property:
loaded  10  items each with  500 subitems
523034 function calls (512957 primitive calls) in 2.556 CPU s
loaded  30  items each with  500 subitems
1564374 function calls (1534297 primitive calls) in 7.796 CPU s
loaded  16  items each with  1500 subitems
2499436 function calls (2451359 primitive calls) in 12.518 CPU s

plain dict:
loaded  10  items each with  500 subitems
513014 function calls (502937 primitive calls) in 2.525 CPU s
loaded  30  items each with  500 subitems
1534314 function calls (1504237 primitive calls) in 7.623 CPU s
loaded  16  items each with  1500 subitems
2451404 function calls (2403327 primitive calls) in 12.196 CPU s

up to you

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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-15 Thread sdobrev

On Tuesday 14 August 2007 23:05:44 Michael Bayer wrote:
 On Aug 14, 2007, at 3:30 PM, [EMAIL PROTECTED] wrote:
  databases/sqlite: (reflecttable)
pragma_names is missing the BOOLEAN word/type - nulltype
 
  btw why isn't each dialect-typeclass adding it's own entry to
  that pragma_names, respectively to the colspecs ?
  Or, each class to have those pragmaword and basetype, and the
  dicts to be made by walking locals() if issubclass(..) ?
 
  Anyway, these dicts (the grammar) should be automaticaly built
  from available typeclasses...

 patches welcome

 
here 2 versions. 
One is simple, walking the module.namespace for 
issubclass(TypeEngine), expecting to find .pragma and .colspec in 
that class and collects them. The .colspec can probably be figured 
out from __bases__ (as in other version)

pre
def _issubclass( obj, klas):
'fail/fool-proof issubclass() - works with ANY argument'
from types import ClassType
return isinstance(obj,(type,ClassType)) and issubclass(obj,klas)

def collect_colspecs( namespace):   #this can be moved out of here
colspecs = {}
pragma_names = {}
for obj in namespace.itervalues():
if _issubclass( kl, sqlalchemy.TypeEngine):
c = getattr( kl, 'colspec', None) #or 'basetype'
p = getattr( kl, 'pragma', None)  #or 'sqltype' or rawtype
if c and p:
colspec[c]=kl
pragma_names[c]=kl
return colspecs, pragma_names

class SLNumeric(sqltypes.Numeric):
colspec,pragma = sqltypes.Numeric, 'NUMERIC'
def get_col_spec(self):
if self.precision is None:
return NUMERIC
else:
return NUMERIC(%(precision)s, %(length)s)%self.__dict__

class SLInteger(sqltypes.Integer):
colspec,pragma = sqltypes.Integer, 'INTEGER'
def get_col_spec(self): return self.pragma
...
colspecs, pragma_names = collect_colspecs( locals() )

/pre



the other one uses metaclass, and .pragma is set up, and guesses 
colspec's abstract_type from __bases.

pre
class MetaDialectType( type):   #this can be moved out of here
def __new__( metacls, name, bases, dict_):
#find top-most abstract_type base 
abstract_type = None
for b in bases:
#XXX is walk in depth needed? 
#e.g. if allowed class SLInt2( SLInteger):...
if issubclass( b, sqltypes.TypeEngine):
abstract_type = b
break
assert abstract_type, 'class %s: cannot find any abstract \
base type; do inherit from some sqlalchemy type' % name

try:
pragma = dict_['pragma']
except KeyError:
assert 0, 'class %s: cannot find any pragma' % name

klas = type.__new__( metacls, name, bases, dict_)
metacls.colspecs[ abstract_type] = klas
metacls.pragma_names[ pragma]=klas
return klas

class SLMetaDialectType( MetaDialectType):
colspecs = {}
pragma_names = {}

class SLNumeric( sqltypes.Numeric):
__metaclass__ = SLMetaDialectType
pragma = 'NUMERIC'
def get_col_spec(self):
r = self.pragma
if self.precision is not None:
r += (%(precision)s, %(length)s) % self.__dict__
return r

class SLInteger( sqltypes.Integer):
__metaclass__ = SLMetaDialectType
pragma = 'INTEGER'
def get_col_spec(self): return self.pragma

...
colspecs = SLMetaDialectType.colspecs
pragma_names = SLMetaDialectType.pragma_names 
/pre

==
There are 2 choices to make: 
 - walk locals() vs using metaclass
 - whether to touch get_col_spec()s 

i wanted to have everything specified only once.
Therefore the get_col_spec() redefinition. 
It can be:
 1 left as is, just adding a separate .pragma (no gain, 
consistency-wise, e.g. VARCHR in one place and VARCHAR in another)
 2 remade to use the self.pragma where equivalent (like 80% of 
places) - a lot of same code repeated
 3 put a default one in some base class for all dialect-types, e.g. 
DialectBaseType, which can be then used for filtering locals() or to 
bring metaclass
 4 created in the metaclass unless explicitly specified - this is most 
obscure.

btw i suggest some namechanges, colspec - abstract_type and 
pragma_name - rawdb_type; or something alike.

ciao
svil

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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-15 Thread Michael Bayer

I had in mind that the metaclass approach would be used, but not  
necesarily with the walking stuff going on.

if you really want to think about this, the idea for a types overhaul  
is ticket #526.  that breaks up the DDL from the adaptation side  
of things.  a metaclass approach would be at the base of it  
controlling a registry of information about types.


On Aug 15, 2007, at 12:15 PM, [EMAIL PROTECTED] wrote:


 On Tuesday 14 August 2007 23:05:44 Michael Bayer wrote:
 On Aug 14, 2007, at 3:30 PM, [EMAIL PROTECTED] wrote:
 databases/sqlite: (reflecttable)
   pragma_names is missing the BOOLEAN word/type - nulltype

 btw why isn't each dialect-typeclass adding it's own entry to
 that pragma_names, respectively to the colspecs ?
 Or, each class to have those pragmaword and basetype, and the
 dicts to be made by walking locals() if issubclass(..) ?

 Anyway, these dicts (the grammar) should be automaticaly built
 from available typeclasses...

 patches welcome


 here 2 versions.
 One is simple, walking the module.namespace for
 issubclass(TypeEngine), expecting to find .pragma and .colspec in
 that class and collects them. The .colspec can probably be figured
 out from __bases__ (as in other version)

 pre
 def _issubclass( obj, klas):
 'fail/fool-proof issubclass() - works with ANY argument'
 from types import ClassType
 return isinstance(obj,(type,ClassType)) and issubclass(obj,klas)

 def collect_colspecs( namespace): #this can be moved out of here
 colspecs = {}
 pragma_names = {}
 for obj in namespace.itervalues():
 if _issubclass( kl, sqlalchemy.TypeEngine):
 c = getattr( kl, 'colspec', None) #or 'basetype'
 p = getattr( kl, 'pragma', None)  #or 'sqltype' or rawtype
 if c and p:
 colspec[c]=kl
 pragma_names[c]=kl
 return colspecs, pragma_names

 class SLNumeric(sqltypes.Numeric):
 colspec,pragma = sqltypes.Numeric, 'NUMERIC'
 def get_col_spec(self):
 if self.precision is None:
 return NUMERIC
 else:
 return NUMERIC(%(precision)s, %(length)s)%self.__dict__

 class SLInteger(sqltypes.Integer):
 colspec,pragma = sqltypes.Integer, 'INTEGER'
 def get_col_spec(self): return self.pragma
 ...
 colspecs, pragma_names = collect_colspecs( locals() )

 /pre

 

 the other one uses metaclass, and .pragma is set up, and guesses
 colspec's abstract_type from __bases.

 pre
 class MetaDialectType( type): #this can be moved out of here
 def __new__( metacls, name, bases, dict_):
 #find top-most abstract_type base
 abstract_type = None
 for b in bases:
 #XXX is walk in depth needed?
 #e.g. if allowed class SLInt2( SLInteger):...
 if issubclass( b, sqltypes.TypeEngine):
 abstract_type = b
 break
 assert abstract_type, 'class %s: cannot find any abstract \
 base type; do inherit from some sqlalchemy type' % name

 try:
 pragma = dict_['pragma']
 except KeyError:
 assert 0, 'class %s: cannot find any pragma' % name

 klas = type.__new__( metacls, name, bases, dict_)
 metacls.colspecs[ abstract_type] = klas
 metacls.pragma_names[ pragma]=klas
 return klas

 class SLMetaDialectType( MetaDialectType):
 colspecs = {}
 pragma_names = {}

 class SLNumeric( sqltypes.Numeric):
 __metaclass__ = SLMetaDialectType
 pragma = 'NUMERIC'
 def get_col_spec(self):
 r = self.pragma
 if self.precision is not None:
 r += (%(precision)s, %(length)s) % self.__dict__
 return r

 class SLInteger( sqltypes.Integer):
 __metaclass__ = SLMetaDialectType
 pragma = 'INTEGER'
 def get_col_spec(self): return self.pragma

 ...
 colspecs = SLMetaDialectType.colspecs
 pragma_names = SLMetaDialectType.pragma_names
 /pre

 ==
 There are 2 choices to make:
  - walk locals() vs using metaclass
  - whether to touch get_col_spec()s

 i wanted to have everything specified only once.
 Therefore the get_col_spec() redefinition.
 It can be:
  1 left as is, just adding a separate .pragma (no gain,
 consistency-wise, e.g. VARCHR in one place and VARCHAR in another)
  2 remade to use the self.pragma where equivalent (like 80% of
 places) - a lot of same code repeated
  3 put a default one in some base class for all dialect-types, e.g.
 DialectBaseType, which can be then used for filtering locals() or to
 bring metaclass
  4 created in the metaclass unless explicitly specified - this is most
 obscure.

 btw i suggest some namechanges, colspec - abstract_type and
 pragma_name - rawdb_type; or something alike.

 ciao
 svil

 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to 

[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-15 Thread sdobrev

On Wednesday 15 August 2007 19:51:30 Michael Bayer wrote:
 On Aug 15, 2007, at 10:52 AM, [EMAIL PROTECTED] wrote:
  Second, i went to r3312, let init_attr() set a _state as plain
  dict and removed _state as property. The difference
  plain-dict/property (in favor of plain dict) is like 2-3%.
 
  property:
  loaded  10  items each with  500 subitems
  523034 function calls (512957 primitive calls) in 2.556 CPU s
  loaded  30  items each with  500 subitems
  1564374 function calls (1534297 primitive calls) in 7.796 CPU s
  loaded  16  items each with  1500 subitems
  2499436 function calls (2451359 primitive calls) in 12.518 CPU s
 
  plain dict:
  loaded  10  items each with  500 subitems
  513014 function calls (502937 primitive calls) in 2.525 CPU s
  loaded  30  items each with  500 subitems
  1534314 function calls (1504237 primitive calls) in 7.623 CPU s
  loaded  16  items each with  1500 subitems
  2451404 function calls (2403327 primitive calls) in 12.196 CPU s
 
  up to you

 great, post a patch for that on trac.
#741, using _sa_attr_state, set-up in mapper._create_instance()

btw (if i havent asked yet) - do u have a place describing all things 
that happen to some user's object/class once given into SA's arms? 
e.g. all the attributes that grow on the instances (and has to be 
avoided by user), replacement of __init__, all the descriptors for 
attributes, etc?
i can prepare something like half a page on this theme, but u'll have 
to fill up as i surely have no much idea of which is what/why.
Title like impact on user's object and class

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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-15 Thread sdobrev

On Wednesday 15 August 2007 20:54:27 Michael Bayer wrote:
 I had in mind that the metaclass approach would be used, but not
 necesarily with the walking stuff going on.
the walking is a quick and dirty and very simple way to get away with 
it - for now.

 if you really want to think about this, the idea for a types
 overhaul is ticket #526.  that breaks up the DDL from the
 adaptation side of things.  a metaclass approach would be at the
 base of it controlling a registry of information about types.

types... my static_type lib is just about types, and all the metainfo 
u could hang on them...

lets see. u have multiple types (and conversions) here, for same item: 
 a) the SA-abstract type in schema - eg. types.String
 b) the specific dialect implementation of a), e.g. sqlite.SLText
 c) the python type that is expected to live between SAdialect and 
dbapi, both ways
 d) the actual SQL server name/representation for the type
 e) python type that is expected to come out from SA of when loading, 
eg. unicode
 f) python type that is expected to go into SA when assigning. eg. 
str/utf8
 g) validation for e) (to SA)
  - so x.myint = 'qq' fails (or x.mystr=12 succeeds)
 h) validation for f) (from SA)
  - so attempting to load x.myint from column containing 'qq' fails

my experience says conversion and validation is same ONE thing, 
implementation-wise. u make one of these notions and use it to 
implement both, e.g. i have static_type.validators which i use for 
conversion and/or validation.

The g,h conversions/validations are outside of sql-related-scope, they 
are only application-side related. i guess they will be mostly 
user-specified, with very few automatical.

For example, in dbcook i set up another layer of type-translation on 
top of SA, exactly to address this issue. So application types stay 
applicational, and match to whatever (independently) at persistency  
level (SA). Thus i can use same model file, with same names, once 
having the (my) types as heavy-checking statictypes, and once as 
empty classes (plainwrap.py) used just to match the SA-type 
underneath.

Each dialect keeps its own registry of types, used for bidirectional 
abstract-dialect match, plus the actual sql (pragma) stuff like 
typenames/args and retrieving them back for reflection. This 
coresponds to current colspecs and pragma_names dicts. Reflection 
should be configurable whether to stop at dialect level (SLint) or go 
back to abstract types (types.Int) - see my autoload.py.

are there any cases of diality? e.g. str1 and str2 both being str?

current situation: IMO right now typewise all is ok, but u have one 
conversion only, happening inside the dialect, implicitly, cannot be 
extended/chained; and registries are separated and inconsistent and 
hard to find.

you wanted also specific converters as per dialect, e.g.
 python.str(-SA.date-SA.sqlite.SLdate)-sqlite.datetime 
might be different from
 python.str(-SA.date-SA.postgress.PGdate)-psycopg.datetime

so, do u want the Convertors/validators network to follow the way of 
Types network? i.e. abstract convertors and (actual) 
dialect-implementations? in another registry?

Are there going to be priorities/ordering in (auto) matching of 
convertors? e.g. u may have str2int and str2anynumber, which to 
choose...

btw. chaining converters changes/pushes expected (i/o) pythontype. The 
question what is the expected in/out pythontype? should ask the 
first converter in the chain from user-side, and result can be 
singular or multiple, e.g. anything to str, or (bool,int,long,float) 
to float).

am i missing something so far?

  btw why isn't each dialect-typeclass adding it's own entry to
  that pragma_names, respectively to the colspecs ?
  Anyway, these dicts (the grammar) should be automaticaly
  built from available typeclasses...
 
  patches welcome
 
  here 2 versions.
  One is simple, walking the module.namespace for
  issubclass(TypeEngine), expecting to find .pragma and .colspec in
  that class and collects them. The .colspec can probably be
  figured out from __bases__ (as in other version)
 
 
  the other one uses metaclass, and .pragma is set up, and guesses
  colspec's abstract_type from __bases.
 
  ==
  There are 2 choices to make:
   - walk locals() vs using metaclass
   - whether to touch get_col_spec()s
 
  i wanted to have everything specified only once.
  Therefore the get_col_spec() redefinition.
  It can be:
   1 left as is, just adding a separate .pragma (no gain,
  consistency-wise, e.g. VARCHR in one place and VARCHAR in
  another) 2 remade to use the self.pragma where equivalent (like
  80% of places) - a lot of same code repeated
   3 put a default one in some base class for all dialect-types,
  e.g. DialectBaseType, which can be then used for filtering
  locals() or to bring metaclass
   4 created in the metaclass unless explicitly specified - this is
  most obscure.
 
  btw i suggest some namechanges, colspec - abstract_type and
  pragma_name 

[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-15 Thread sdobrev

 Reflection should be configurable whether to stop at dialect 
 level (SLint) or go back to abstract types (types.Int) - see my
 autoload.py.
why would one want to stop the reflection from going back to abstract 
types?
i.e. if the current reflection (dialevt-level) is made to autoguess 
the abstract SA type, would this break something?


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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-15 Thread sdobrev

On Thursday 16 August 2007 00:33:57 [EMAIL PROTECTED] wrote:
  Reflection should be configurable whether to stop at dialect
  level (SLint) or go back to abstract types (types.Int) - see my
  autoload.py.

 why would one want to stop the reflection from going back to
 abstract types?
 i.e. if the current reflection (dialevt-level) is made to autoguess
 the abstract SA type, would this break something?

Answering myself, dialects may have richer types that SA.abstract 
ones, in which case extra ones stay as is.

Also, seems there are duplicates, because of which the 
abstract-dialect is not 1:1, e.g. postgres has bigint and int that 
are both SA.integer. how about these?

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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-14 Thread svilen


performance-wise - do u have any test/target for profiling? else i can 
repeat some tests i did somewhen in february (if i remember them..)

=

while looking to replace all {} with dict/Dict(), i found some things. 
Here the list, quite random, probably some can be just ignored if not 
an actual issue - i may have misunderstood things; have a look.
(btw The overall candidates for the replacement are like 60-70 lines, 
all else are kwargs or lookup-tables.)

---
database/informix.py:
  ischema_names = { ... }  has duplicate keys/entries

---
database/*
  get_col_spec(self) etc:
these string-formats may be better without the artificial dict,
 eg. return self._extend(CHAR(%(length)s) % {'length': self.length})
 - return self._extend(CHAR(%s) % self.length )
  or
 - return self._extend(CHAR(%(length)s) % self.__dict__ )
no idea if get_col_spec() is used that much to have crucial impact on 
speed though, at least it looks simpler.

---
orm.util.AliasedClauses._create_row_adapter()
class AliasedRowAdapter( object):
 1. can't this be made as standalone class, returning an instance, 
initialized with the map, which is then __call__()ed ?
 2. this can be faster if: 
a) has_key = __contains__ #instead of yet another funccall
b) __getitem__ uses try except instead of double lookup key in map

---
orm.mapper
 Mapper._instance():
WTF is the **{'key':value, ... } ?
eg. if extension.populate_instance(self, context, row, instance, 
**{'instancekey':identitykey, 'isnew':isnew}) ...
same thing is done as separate variable a page later;
btw there are several of these **{} in the file

 also, Mapper._options is redundant (leftover?) neverused


---
orm.attribute
  AttributeManager.init_attr():
the saving this one eventualy does is too small, compared to a 
property call of ._state.

  AttributeManager.register_attribute():
the  def _get_state(self) that is made into as property _state can 
be made eventualy faster with try-except instead of 'if'.

 btw: cant that ._state property be removed alltogether (i.e. made a 
plain attribute? then init_attr() MUST be there seting it up as plain 
dict.

---
orm/unitofwork
UOWTask._sort_circular_dependencies():
def get_dependency_task(obj, depprocessor):
try:
dp = dependencies[obj]
except KeyError:
dp = dependencies.setdefault(obj, {})
isnt just the setdefault() enough?

---
engine.url.
  def translate_connect_args(self, names):
this assumes the order of passed names matches the order of 
attribute_names inside... very fragile. Why not use set of kwargs 
like (attr_name=replacement_name defaulting to None), then just use 
the non empty ones?
  def _parse_rfc1738_args():
the 'opts' dict is redundant, would be cleaner if args are just 
passed to URL( name=value)

---
topological.py
   QueueDependencySorter.sort():
  'cycles' is redundant neverused variable

---
util:
  ThreadLocal:
   - wouldnt be faster if the key in the _tdict is tuple(id,key) and 
not some formatted string off these? or the key is nonhashable?
   - the engine/threadlocal.TLEngine._session() issues a hasattr() on 
such object. how does it actualy work? IMO it always fails

==
hey, thanks for the MetaData.reflect()!

svil

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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-14 Thread Brian Beck

On Aug 14, 11:29 am, Michael Bayer [EMAIL PROTECTED] wrote:
 I just put beta2 up.  The important things in this release are major
 MS-SQL and Oracle fixes, after we got some on-the-ground testing done.

 Theres also a new function we're planning to use in Pylons called
 engine_from_config(), which reads a configuration dictionary (such
 as from a .ini file) and returns an Engine instance.

 Also some enhancements to Session.execute() which may become important
 as we move more towards the session-as-executor model; if you are
 using multiple engines, execute() will search through the
 ClauseElement for tables that it can link to bound engines, thus
 reducing the need to pass a mapper along to it.

0.4 looks awesome. Some names jump out at me though:
* sessionmaker - Strange that it's a noun, and not a verb (like
make_session)
* bind/binds arguments - Strange that it's a verb, and not a noun (why
not engine/engines?)

Keep up the good work!

--
Brian Beck / Adventurer of the First Order / www.brianbeck.com


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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-14 Thread sdobrev

databases/sqlite: (reflecttable)
  pragma_names is missing the BOOLEAN word/type - nulltype

btw why isn't each dialect-typeclass adding it's own entry to that 
pragma_names, respectively to the colspecs ? 
Or, each class to have those pragmaword and basetype, and the dicts to 
be made by walking locals() if issubclass(..) ?

Anyway, these dicts (the grammar) should be automaticaly built from 
available typeclasses...

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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-14 Thread Michael Bayer


On Aug 14, 2007, at 3:30 PM, [EMAIL PROTECTED] wrote:


 databases/sqlite: (reflecttable)
   pragma_names is missing the BOOLEAN word/type - nulltype

 btw why isn't each dialect-typeclass adding it's own entry to that
 pragma_names, respectively to the colspecs ?
 Or, each class to have those pragmaword and basetype, and the dicts to
 be made by walking locals() if issubclass(..) ?

 Anyway, these dicts (the grammar) should be automaticaly built from
 available typeclasses...

patches welcome

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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-14 Thread Michael Bayer


On Aug 14, 2007, at 12:38 PM, svilen wrote:



 performance-wise - do u have any test/target for profiling? else i can
 repeat some tests i did somewhen in february (if i remember them..)

look in test/perf for some, just added a mass-insert/mass-select test.

also the current branch im doing today will chop out about 60% of  
function call overhead from the abovementioned test.

 ---
 database/*
   get_col_spec(self) etc:
 these string-formats may be better without the artificial dict,
  eg. return self._extend(CHAR(%(length)s) % {'length': self.length})
  - return self._extend(CHAR(%s) % self.length )
   or
  - return self._extend(CHAR(%(length)s) % self.__dict__ )
 no idea if get_col_spec() is used that much to have crucial impact on
 speed though, at least it looks simpler.

im fine with that (not crucial tho)


 ---
 orm.util.AliasedClauses._create_row_adapter()
 class AliasedRowAdapter( object):
  1. can't this be made as standalone class, returning an instance,
 initialized with the map, which is then __call__()ed ?

is it faster to say self.map or to say map from locals() ?  its  
probably not very crucial either way.

  2. this can be faster if:
 a) has_key = __contains__ #instead of yet another funccall
 b) __getitem__ uses try except instead of double lookup key in map

im not sure try/except is faster here - im pretty sure a missing key  
is likely and exception throws are very expensive.  would be worth a  
try to see if the missing key exception actually occurs here.


 ---
 orm.mapper
  Mapper._instance():
 WTF is the **{'key':value, ... } ?
 eg. if extension.populate_instance(self, context, row, instance,
 **{'instancekey':identitykey, 'isnew':isnew}) ...
 same thing is done as separate variable a page later;
 btw there are several of these **{} in the file

i think thats a product of a refactoring where the ** was originally  
not there.


  also, Mapper._options is redundant (leftover?) neverused

yeah gone along with the **{} in r3303



 ---
 orm.attribute
   AttributeManager.init_attr():
 the saving this one eventualy does is too small, compared to a
 property call of ._state.

i havent benched this in a while but my recollection is that the  
AttributeError raise is *much* slower than pre-calling this method.   
a single function call is always faster than an exception throw.

however, i see that the exception throw is being suppressed also with  
a hasattr() being called every timeim not sure why thats that way  
now so i might change it back to throwing AttributeError.



   AttributeManager.register_attribute():
 the  def _get_state(self) that is made into as property _state can
 be made eventualy faster with try-except instead of 'if'.

exception throws are slower.  but like above says, the throw here can  
be prevented if init_attr() is called.


  btw: cant that ._state property be removed alltogether (i.e. made a
 plain attribute? then init_attr() MUST be there seting it up as plain
 dict.

it should be named something non-collisionworthy such as the current  
_sa_attr_state.


 ---
 orm/unitofwork
 UOWTask._sort_circular_dependencies():
 def get_dependency_task(obj, depprocessor):
 try:
 dp = dependencies[obj]
 except KeyError:
 dp = dependencies.setdefault(obj, {})
   isnt just the setdefault() enough?

this should just say dependencies[obj] = dp = {}


 ---
 engine.url.
   def translate_connect_args(self, names):
 this assumes the order of passed names matches the order of
 attribute_names inside... very fragile. Why not use set of kwargs
 like (attr_name=replacement_name defaulting to None), then just use
 the non empty ones?

patches welcome

   def _parse_rfc1738_args():
 the 'opts' dict is redundant, would be cleaner if args are just
 passed to URL( name=value)

this is an old patch we got from someone, improvement patches welcome


 ---
 topological.py
QueueDependencySorter.sort():
   'cycles' is redundant neverused variable

would look good in the patch too


 ---
 util:
   ThreadLocal:
- wouldnt be faster if the key in the _tdict is tuple(id,key) and
 not some formatted string off these? or the key is nonhashable?

good catch, should be patched

- the engine/threadlocal.TLEngine._session() issues a hasattr() on
 such object. how does it actualy work? IMO it always fails

patch which includes a test case to add into test/engine/ 
transaction.py would be welcome




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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-14 Thread Michael Bayer


On Aug 14, 2007, at 2:12 PM, Brian Beck wrote:


 0.4 looks awesome. Some names jump out at me though:
 * sessionmaker - Strange that it's a noun, and not a verb (like
 make_session)

the verb would be, make_session_maker.  or make_session_class,  
except in some cases it might not be an actual class...

 * bind/binds arguments - Strange that it's a verb, and not a noun (why
 not engine/engines?)

bind is used as a noun here.  it is slightly weird and there was  
much discussion about this so youre a little late for that train :).   
the reason its not engine anymore is because it can be a Connection  
also.  engines and connections are collectively called  
connectables, but nobody understood that term...so its bind.



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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-14 Thread sdobrev

  orm.util.AliasedClauses._create_row_adapter()
  class AliasedRowAdapter( object):
   1. can't this be made as standalone class, returning an
  instance, initialized with the map, which is then __call__()ed ?

 is it faster to say self.map or to say map from locals() ?  its
 probably not very crucial either way.
well.. u save on class' creation :-), get a class that could be used 
elsewhere, and eventualy more obvious code - runtime outer-namespace 
bindings in python are veeery strange beasts sometimes, with funny 
side effects.

   2. this can be faster if:
  a) has_key = __contains__ #instead of yet another funccall
  b) __getitem__ uses try except instead of double lookup key
  in map

 im not sure try/except is faster here - im pretty sure a missing
 key is likely and exception throws are very expensive.  would be
 worth a try to see if the missing key exception actually occurs
 here.
i'll have to check, last 3 years i've being doing everything assuming 
that a (lookup:exception) is faster than 
(lookup-if-lookup:lookup-else) in both attribute and dict lookups. 
Plus that a function call is the most expensive python thing ever... 
apart of repeated a.x a.x a.x attribute access. h time to measure 
the myths.

  ---
  orm.attribute
AttributeManager.init_attr():
  the saving this one eventualy does is too small, compared to
  a property call of ._state.

 i havent benched this in a while but my recollection is that the
 AttributeError raise is *much* slower than pre-calling this method.
 a single function call is always faster than an exception throw.

 however, i see that the exception throw is being suppressed also
 with a hasattr() being called every timeim not sure why thats
 that way now so i might change it back to throwing AttributeError.

   btw: cant that ._state property be removed alltogether (i.e.
  made a plain attribute? then init_attr() MUST be there seting it
  up as plain dict.

 it should be named something non-collisionworthy such as the
 current _sa_attr_state.
the only gain from the property is that it is readonly, i.e. 
obj._state = None is not allowed (as well as del'ete). But i can do 
obj._sa_attr_state = None (and all goes to hell). If that property 
disappears alltogether, we are left with a plain _sa_attr_state 
attribute, which can be now set to None and deleted... which is more 
or less same as before less the complications with the property.
Fair trade, no?

  ---
  util:
ThreadLocal:
 - wouldnt be faster if the key in the _tdict is tuple(id,key)
  and not some formatted string off these? or the key is
  nonhashable?

 good catch, should be patched

 - the engine/threadlocal.TLEngine._session() issues a
  hasattr() on such object. how does it actualy work? IMO it always
  fails

 patch which includes a test case to add into test/engine/
 transaction.py would be welcome

i've never used these so no much idea what to do here - was just 
passing code along my eyeline.

will prepare some patches for the other things.

ciao
svilen

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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-14 Thread Jonathan Ellis

On 8/14/07, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote:
  im not sure try/except is faster here - im pretty sure a missing
  key is likely and exception throws are very expensive.  would be
  worth a try to see if the missing key exception actually occurs
  here.
 i'll have to check, last 3 years i've being doing everything assuming
 that a (lookup:exception) is faster than
 (lookup-if-lookup:lookup-else) in both attribute and dict lookups.

Only if, like Mike said, the common case is for the key to be present.

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



[sqlalchemy] Re: SQLAlchemy 0.4 beta2 released

2007-08-14 Thread Michael Bayer


On Aug 14, 2007, at 4:35 PM, Michael Bayer wrote:

 On Aug 14, 2007, at 12:38 PM, svilen wrote:


 ---
 orm.attribute
   AttributeManager.init_attr():
 the saving this one eventualy does is too small, compared to a
 property call of ._state.

 i havent benched this in a while but my recollection is that the
 AttributeError raise is *much* slower than pre-calling this method.
 a single function call is always faster than an exception throw.

 however, i see that the exception throw is being suppressed also with
 a hasattr() being called every timeim not sure why thats that way
 now so i might change it back to throwing AttributeError.

the results are in, running test/prof/masseagerload.py.  this test is  
very heavy on creating new instances from mapper rows, which is where  
the initialization of _state comes in.

no init_attr(), detect missing with AttributeError
Profiled target 'masseagerload', wall time: 0.59 seconds
Profile report for target 'masseagerload' (masseagerload.prof)
57039 function calls (55962 primitive calls) in 0.489 CPU seconds

init_attr(), detect missing with AttributeError
Profiled target 'masseagerload', wall time: 0.53 seconds
57549 function calls (56472 primitive calls) in 0.426 CPU seconds

init_attr(), detect missing with hasattr
Profiled target 'masseagerload', wall time: 0.56 seconds
57549 function calls (56472 primitive calls) in 0.431 CPU seconds

no init_attr(), detect missing with hasattr
Profiled target 'masseagerload', wall time: 0.49 seconds
57039 function calls (55962 primitive calls) in 0.390 CPU seconds

im not exactly sure why the hasattr() call, being present and then  
removed, doesnt change the number of function calls.  anyway,  the  
times vary a little bit but the hasattr call, even though its  
called many more times than the AttributeError gets raised, is  
slightly faster than raising AttributeError.  so no AttributeError,  
and I like getting rid of init_attr() very much so its out in r3313.




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