[sqlalchemy] sqlalchemy-migrate 0.7 released

2011-05-27 Thread Jan Dittberner
Hello,

today I released sqlalchemy-migrate 0.7. This is the first sqlalchemy-migrate
release supporting SQLAlchemy 0.7.0. The only other new functionality is an
added migrate.__version__ (requested in issue 111).

You can get the new release from our download page [1] or PyPI [2].

The sqlalchemy-migrate maintenance has stalled a bit as some of you might have
noticed. We encourage interested developers to join the team and have a look at
[3] for a start. Feel free to ask questions on IRC (#sqlalchemy-migrate on
Freenode).

[1] http://code.google.com/p/sqlalchemy-migrate/downloads/list
[2] http://pypi.python.org/pypi/sqlalchemy-migrate
[3] http://code.google.com/p/sqlalchemy-migrate/wiki/Development


Regards
Jan Dittberner

-- 
Jan Dittberner - Debian Developer
GPG-key: 4096R/558FB8DD 2009-05-10
 B2FF 1D95 CE8F 7A22 DF4C  F09B A73E 0055 558F B8DD
http://www.dittberner.info/


signature.asc
Description: Digital signature


Re: [sqlalchemy] Deferred properties are sometimes compiled unnecessarily?

2011-05-27 Thread Nathan Wright

On Thursday, 26 May 2011 06:42:55 UTC-7, Michael Bayer wrote:


 On May 25, 2011, at 10:52 PM, Nathan Wright wrote:

  Hi all,
  
  I've run into an issue when mapping a deferred column_property that uses 
 a custom SQL construct. I get a KeyError: 'default' because there is no 
 compile function for the default dialect, but it seems to me that the 
 default dialect should never be used.
  
  Here's an extended stack trace of what's going on, the important bit is 
 lines 78-90:
  http://pastebin.com/0kVf9q9q
  
  And here's the a simplified test case:
  
  class utcnow(expression.FunctionElement):
  type = DateTime()
  
  @compiles(utcnow, 'postgresql')
  def pg_utcnow(element, compiler, **kw):
  return TIMEZONE('utc', CURRENT_TIMESTAMP)
  
  mapper(AnyClass, any_table, properties={
  'timestamp': column_property(select([utcnow()]), deferred=True)
  })
  
  Session.query(AnyClass).all() 
  
  
  For now I'm just adding a dummy @compiles(utcnow) function for the 
 default dialect, but I think this could be avoided entirely by changing the 
 NoSuchColumnError message to not cast key (ie, the select) to a string. 
 Perhaps the repr could be used instead?

 the __repr__() produces IMHO a less descriptive string in the case of a no 
 such column type of situation:

 sqlalchemy.exc.NoSuchColumnError: Could not locate column in row for 
 column 'sqlalchemy.sql.expression._Label object at 0x1124490'


 Being able to see the expression is most meaningful.

 http://www.sqlalchemy.org/trac/ticket/2178 provides a patch, which is an 
 improvement on the situation.


Now that I see that use case, I'm in total agreement — seeing the full 
expression when working with a result proxy is very helpful.

I've attached a couple of patches to that issue which avoid compiling the 
expression for internal exceptions. I wasn't sure which approach to take, so 
each patch takes a slightly different approach and you can decide if either 
is suitable :)

Thanks,
Nathan

-- 
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 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] sqlalchemy-migrate 0.7.1 released

2011-05-27 Thread Jan Dittberner
Hello,

I just released sqlalchemy-migrate 0.7.1 fixing the behaviour of
ChangesetColumn.create() as only functional change.

You can get the new release from our download page [1] or PyPI [2].

[1] http://code.google.com/p/sqlalchemy-migrate/downloads/list
[2] http://pypi.python.org/pypi/sqlalchemy-migrate


Regards
Jan Dittberner

-- 
Jan Dittberner - Debian Developer
GPG-key: 4096R/558FB8DD 2009-05-10
 B2FF 1D95 CE8F 7A22 DF4C  F09B A73E 0055 558F B8DD
http://www.dittberner.info/


signature.asc
Description: Digital signature


[sqlalchemy] consistency problem while using ordering_list

2011-05-27 Thread NiL
Hi list,

my use case is along those lines, I want collections to maintain an
ordered list of items.
items can belong to many collections.
when an item is deleted, I'd like the list of items from the
collection to be updated, and ready to be changed again

the comments in the test from the code below show what's go wrong
I'm aware of the reorder_on_append option, but the source is
discouraging, I'm not even sure it is the way to go

reorder_on_append
  Default False.  When appending an object with an existing
(non-None)
  ordering value, that value will be left untouched unless
  ``reorder_on_append`` is true.  This is an optimization to
avoid a
  variety of dangerous unexpected database writes.

so, my questions are :

- is there a way to obtain the expected behaviour ? how?

thanks

NIL
-

# -*- coding: utf-8 -*-
from nose.plugins.attrib import attr
import unittest

from sqlalchemy import (create_engine, Column, Integer,
String, ForeignKey, )
from sqlalchemy.orm import relationship
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.associationproxy import AssociationProxy
from sqlalchemy.ext.orderinglist import ordering_list

from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
engine = create_engine('sqlite:///sqlaordering.db')
Session = sessionmaker(bind=engine)
session = Session()

from sqlalchemy.orm.interfaces import MapperExtension

class ReorderCollection(MapperExtension):
def after_delete(self, mapper, connection, instance):
# this isn't efficient at this stage
instance.collection._item_orders.reorder()

class Item(Base):
__tablename__ = 'items'

id = Column(Integer, primary_key=True)
name = Column(String(50))

_item_orders = relationship(ItemOrder,
cascade='all, delete-orphan',
backref='item',
)

def __init__(self, name):
self.name = name

def __repr__(self):
return '%r %r' \
   % (self.__class__.__name__.capitalize(), self.name)

def _create_item_order(item):
return ItemOrder(item=item)

class Collection(Base):
__tablename__ = 'collections'

id = Column(Integer, primary_key=True)
name = Column(String(50))

_item_orders = relationship(ItemOrder,
cascade='all, delete-orphan',
backref='collection',
order_by=ItemOrder.position,
 
collection_class=ordering_list('position'),
)
items = AssociationProxy(_item_orders, item,
 creator=_create_item_order)

def __init__(self, name):
self.name = name

def __repr__(self):
return '%r %r' \
   % (self.__class__.__name__.capitalize(), self.name)

class ItemOrder(Base):
__tablename__ = 'item_orders'

id = Column(Integer, primary_key=True)
item_id = Column(Integer, ForeignKey('items.id'))
collection_id = Column(Integer, ForeignKey('collections.id'))
position = Column(Integer)
__mapper_args__ = {'extension': ReorderCollection()}


class TestOrderedRelation(unittest.TestCase):

def setUp(self):
Method used to build a database
Base.metadata.create_all(engine)
session.add_all([Item('T-Shirt'),
 Item('Mug'),
 Item('Hat'),
 Item('Shoes'),
 Collection('first'),
 Collection('second'),
 ])
session.commit()


def tearDown(self):
Method used to destroy a database
Base.metadata.drop_all(engine)


@attr('do_it')
def test_problem(self):


first = session.query(Collection).first()
shirt = session.query(Item).get(1)
mug = session.query(Item).get(2)
hat = session.query(Item).get(3)
shoes = session.query(Item).get(4)
first.items.append(shirt)
first.items.append(mug)
first.items.append(mug)
first.items.append(shoes)
session.commit()

assert first.items == [shirt, mug, mug, shoes]
session.delete(mug)
session.commit()
# it seems nice
assert first.items == [shirt, shoes]
first.items.append(hat)
assert first.items == [shirt, shoes, hat]
# but at this point the positions are wrong
assert session.query(ItemOrder.position).all() == [(0,), (3,),
(2,)]
session.commit()
# the list 'magically' changed (no magic, just wrong index)
self.assertFalse(first.items == [shirt, shoes, hat])
# hat took index from len of list when it was inserted
assert first.items == [shirt, hat, shoes]
# worse indices are still wrong
assert