[sqlalchemy] sqlacodegen 2.0.0 released

2018-05-20 Thread Alex Grönholm
After a quiet period of 3 years, I've now made a new major release. This 
release fixes a huge number of bugs and supports the latest SQLAlchemy and 
latest Python versions as well. It also adds support for Geoalchemy2.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


[sqlalchemy] Multi-table deletes with PostgreSQL

2016-09-16 Thread Alex Grönholm


I'm attempting to do a multi-table delete against PostgreSQL (psycopg2) with 
the following query:


session.query(ProductionItem).\
filter(Project.id == ProductionItem.project_id,

   Project.code.in_(projects),

   ProductionItem.external_id.is_(None)).\

delete(synchronize_session=False)


But it produces incorrect SQL. PostgreSQL requires the following syntax for 
this query:


DELETE FROM production_items USING projects WHERE 
production_items.project_id = project.id AND project.code IN (...) AND 
production_items.external_id IS NONE


Instead, I get this:


DELETE FROM production_items WHERE production_items.project_id = project.id 
AND project.code IN (...) AND production_items.external_id IS NONE


At which point PG complains:


sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) missing 
FROM-clause entry for table "projects"


>From initial research this seems like a missing feature. Would it be 
possible to add this to the postgresql dialect somehow? I might be willing 
to contribute the code in that case.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


Re: [sqlalchemy] Rolling back the session in a context manager

2016-07-16 Thread Alex Grönholm

15.07.2016, 16:55, Mike Bayer kirjoitti:



On 07/15/2016 07:49 AM, Alex Grönholm wrote:

The documentation provides the following example snippet for using
sessions within a context manager:


so, back when I started putting "examples" in those docs, the idea was 
like, "hey, here's an *example*.  The Python programmer is free to do 
whatever they wish with these examples, and adjust as necessary".


That is, the reason something is an example and not a feature is, "you 
don't have to do it this way!  do it however you want".


That there's been a trend recently of examples being used as is, but 
then when the example lacks some feature they result in bug reports 
against the library itself (not this case, but a different case 
recently comes to mind), is sadly the opposite of what i had 
intended.  Of course examples can be modified to be reasonable, however.
The question here was raised in part by someone on IRC using the example 
code verbatim, and in part by myself having come up with nearly 
identical code – only with the "except" block missing. I am having odd 
random issues with all sessions randomly ending up in a partial rollback 
state and I can't figure out why. Restarting the application corrects 
the problem and it may not surface again for a couple weeks, so it's 
extremely difficult to debug. That's why I'm asking if I'm missing 
something important by leaving out the rollback() in the teardown phase.






@contextmanager
def session_scope():
"""Provide a transactional scope around a series of operations."""
session = Session()
try:
yield session
session.commit()
except:
session.rollback()
raise
finally:
session.close()

I've been wondering why there is an except: block there. Shouldn't
session.close() be enough? At least according to the documentation, the
active transaction is rolled back by default when the connection is
returned to the pool.



that is correct.  However .close() does not reset the state of the 
objects managed by the Session to be "expired", which arguably is 
necessary because without the transaction, you now have no idea what 
the state of the object's corresponding rows in the database are (this 
is what the whole "SQLAlchemy Session: In Depth" talk is about).


In reality, the above context manager is probably not that useful 
because it bundles the lifespan of the Session and the lifespan of a 
transaction together, and IMO an application should be more thoughtful 
than that.
Yep – I have similar code adapted to an "extension" where the teardown 
phase is run after the current RPC request is done.





This snippet has a second potential problem: what if the transaction is
in a bad state when exiting the block? Shouldn't session.commit() be
skipped then?


it's assumed that if anything is in "a bad state" then an exception 
would have been raised, you'd not reach commit().


Otherwise, if the idea is, "I'm using this context manager, but I'm 
not sure I want to commit at the end even though nothing was raised", 
well then this is not the context manager for you :). The example of 
contextmanagers for things like writing files and such sets up the 
convention of, "open resource, flush out all changes at the end if no 
exceptions".   That's what people usually want.


Yes, committing at the end by default is reasonable. But that wasn't 
what my question was about.


Like, if not session.is_active: session.commit()? Let's

say the user code catches IntegrityError but doesn't roll back.


if it doesn't re-raise, then we'd hit the commit() and that would 
probably fail also (depending on backend).  I don't see how that's 
different from:


with open("important_file.txt", "w") as handle:
handle.write("important thing #1")
handle.write("important thing #2")
try:
 important_thing_number_three = calculate_special_thing()
 handle.write(important_thing_number_three)
except TerribleException:
 log.info("oh crap! someone should fix this someday.")
handle.write("important thing #4")
I was thinking of a situation where the code doesn't use the session at 
all after catching the IntegrityError.







The

example code will then raise an exception when it tries to commit the
session transaction. Am I missing something?


On the better backends like Postgresql, it would.

If there's a use case you're looking for here, e.g. catch an 
IntegrityError but not leave the transaction, that's what savepoints 
are for.   There should be examples there.
No, my point was that if I catch the IntegrityError and don't raise 
anything from that, I don't intend to raise any exception afterwards 
either. In which case commit should not be attempted at all.




Now, if someone on IRC is using savepoi

[sqlalchemy] Rolling back the session in a context manager

2016-07-15 Thread Alex Grönholm
The documentation provides the following example snippet for using sessions 
within a context manager:

@contextmanagerdef session_scope():
"""Provide a transactional scope around a series of operations."""
session = Session()
try:
yield session
session.commit()
except:
session.rollback()
raise
finally:
session.close()

I've been wondering why there is an except: block there. Shouldn't 
session.close() be enough? At least according to the documentation, the 
active transaction is rolled back by default when the connection is 
returned to the pool.
This snippet has a second potential problem: what if the transaction is in 
a bad state when exiting the block? Shouldn't session.commit() be skipped 
then? Like, if not session.is_active: session.commit()? Let's say the user 
code catches IntegrityError but doesn't roll back. The example code will 
then raise an exception when it tries to commit the session transaction. Am 
I missing something?

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


[sqlalchemy] Trouble with AbstractConcreteBase and aliased columns

2015-07-09 Thread Alex Grönholm
The following script no longer works in 1.0.6, but does in 0.9.9:


from sqlalchemy.ext.declarative import declarative_base, AbstractConcreteBase
from sqlalchemy.ext.declarative.api import declared_attr
from sqlalchemy.orm.mapper import configure_mappers
from sqlalchemy.orm.session import Session
from sqlalchemy.sql.schema import Column, ForeignKey
from sqlalchemy.sql.sqltypes import Date, String, Integer

Base = declarative_base()


class Company(Base):
__tablename__ = 'companies'
id = Column(Integer, primary_key=True)


class Document(object):
date = Column(Date)
documentType = Column('documenttype', String)


class ContactDocument(AbstractConcreteBase, Base, Document):
contactPersonName = Column('contactpersonname', String)
salesPersonName = Column(String)
sendMethod = Column('sendmethod', String)

@declared_attr
def company_id(self):
return Column(ForeignKey('companies.id'))


class Offer(ContactDocument):
__tablename__ = 'offers'

id = Column(Integer, primary_key=True)


class SalesOrder(ContactDocument):
__tablename__ = 'orders'

id = Column(Integer, primary_key=True)


configure_mappers()
session = Session()
query = session.query(ContactDocument)
print(query)



On 1.0.6, I get an error: sqlalchemy.exc.ArgumentError: When configuring 
property 'documentType' on Mapper|ContactDocument|pjoin, column 
'documenttype' is not represented in the mapper's table. Use the 
`column_property()` function to force this column to be mapped as a 
read-only attribute.
Why am I getting this? Is this a bug or am I not understanding something?

Also, is it possible to have both Document and ContactDocument as abstract 
concrete base classes (ie. I want the union from Document to include both 
the direct concrete subclasses of Document and all concrete subclasses of 
ContactDocument as well)?

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


Re: [sqlalchemy] Trouble with AbstractConcreteBase and aliased columns

2015-07-09 Thread Alex Grönholm
Thanks. What about my other question? Is it possible to have two layers of 
classes (Document and ContactDocument) mapped to polymorphic unions?

torstai 9. heinäkuuta 2015 18.31.36 UTC+3 Michael Bayer kirjoitti:

  Thanks for reporting.   Issue 
 https://bitbucket.org/zzzeek/sqlalchemy/issues/3480/abstractconcretebase-regression-with
  
 is created, create the Column objects with an explicit key for now:


 class Document(object):
 date = Column(Date)
 documentType = Column('documenttype', String, key=documentType)


 class ContactDocument(AbstractConcreteBase, Base, Document):
 contactPersonName = Column('contactpersonname', String, 
 key=contactPersonName)
 salesPersonName = Column(String)
 sendMethod = Column('sendmethod', String, key=sendMethod)

 @declared_attr
 def company_id(self):
 return Column(ForeignKey('companies.id'))



 On 7/9/15 11:18 AM, Alex Grönholm wrote:
  
 The following script no longer works in 1.0.6, but does in 0.9.9:


 from sqlalchemy.ext.declarative import declarative_base, 
 AbstractConcreteBasefrom sqlalchemy.ext.declarative.api import 
 declared_attrfrom sqlalchemy.orm.mapper import configure_mappersfrom 
 sqlalchemy.orm.session import Sessionfrom sqlalchemy.sql.schema import 
 Column, ForeignKeyfrom sqlalchemy.sql.sqltypes import Date, String, Integer

 Base = declarative_base()

 class Company(Base):
 __tablename__ = 'companies'id = Column(Integer, primary_key=True)

 class Document(object):
 date = Column(Date)
 documentType = Column('documenttype', String)

 class ContactDocument(AbstractConcreteBase, Base, Document):
 contactPersonName = Column('contactpersonname', String)
 salesPersonName = Column(String)
 sendMethod = Column('sendmethod', String)

 @declared_attrdef company_id(self):
 return Column(ForeignKey('companies.id'))

 class Offer(ContactDocument):
 __tablename__ = 'offers'id = Column(Integer, primary_key=True)

 class SalesOrder(ContactDocument):
 __tablename__ = 'orders'id = Column(Integer, primary_key=True)


 configure_mappers()
 session = Session()
 query = session.query(ContactDocument)print(query)



 On 1.0.6, I get an error: sqlalchemy.exc.ArgumentError: When configuring 
 property 'documentType' on Mapper|ContactDocument|pjoin, column 
 'documenttype' is not represented in the mapper's table. Use the 
 `column_property()` function to force this column to be mapped as a 
 read-only attribute.
 Why am I getting this? Is this a bug or am I not understanding something?

 Also, is it possible to have both Document and ContactDocument as abstract 
 concrete base classes (ie. I want the union from Document to include both 
 the direct concrete subclasses of Document and all concrete subclasses of 
 ContactDocument as well)?
  -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to sqlalchemy+...@googlegroups.com javascript:.
 To post to this group, send email to sqlal...@googlegroups.com 
 javascript:.
 Visit this group at http://groups.google.com/group/sqlalchemy.
 For more options, visit https://groups.google.com/d/optout.


 

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


[sqlalchemy] sqlacodegen 1.1.6 released.

2015-05-15 Thread Alex Grönholm
This update only fixes compatibility with SQLAlchemy 1.0.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


Re: [sqlalchemy] More than one level of abstract base classes doesn't work

2014-09-05 Thread Alex Grönholm
Thanks. I've filed an issue 
https://bitbucket.org/zzzeek/sqlalchemy/issue/3185/more-than-one-level-of-abstract-concrete
 
at Bitbucket.

A follow-up question: Why are abstract base classes not present in the 
declarative class registry? Or is there another way to get all the mapped 
classes besides iterating over Base._decl_class_registry?

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


Re: [sqlalchemy] More than one level of abstract base classes doesn't work

2014-09-05 Thread Alex Grönholm
You're right, I'm dumb. I should've just used __subclasses__ and be done 
with it.
The use case is that I have a client-server app and I build a list of all 
classes for the client so the client knows which column types to use in 
tables. It's also used for automatically generating the column/relationship 
list on the client in the search dialog. So I won't have to make code 
changes to the client when I alter the model on the server.

perjantai, 5. syyskuuta 2014 17.13.10 UTC+3 Michael Bayer kirjoitti:

 well it’s not set to be mapped until after the setup part of it.   

 if you want to get every class whether mapped or not, maybe use 
 Base.__subclasses__() ?

 What’s the use case where you need the abstract base in the decl class 
 registry?  it’s not really something you’d want to refer to in a 
 relationship().



 On Sep 5, 2014, at 9:56 AM, Alex Grönholm alex.g...@nextday.fi 
 javascript: wrote:

 Thanks. I've filed an issue 
 https://bitbucket.org/zzzeek/sqlalchemy/issue/3185/more-than-one-level-of-abstract-concrete
  
 at Bitbucket.

 A follow-up question: Why are abstract base classes not present in the 
 declarative class registry? Or is there another way to get all the mapped 
 classes besides iterating over Base._decl_class_registry?

 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to sqlalchemy+...@googlegroups.com javascript:.
 To post to this group, send email to sqlal...@googlegroups.com 
 javascript:.
 Visit this group at http://groups.google.com/group/sqlalchemy.
 For more options, visit https://groups.google.com/d/optout.




-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


Re: [sqlalchemy] More than one level of abstract base classes doesn't work

2014-09-05 Thread Alex Grönholm
Hm not so dumb actually, because __subclasses__ only lists immediate 
subclasses. Getting all the mapped classes would involve more work that 
way. So my preferred method remains this:

def get_all_mapped_classes():
return [cls for cls in Base._decl_class_registry.values() if isinstance(
cls, type)]


perjantai, 5. syyskuuta 2014 17.19.21 UTC+3 Alex Grönholm kirjoitti:

 You're right, I'm dumb. I should've just used __subclasses__ and be done 
 with it.
 The use case is that I have a client-server app and I build a list of all 
 classes for the client so the client knows which column types to use in 
 tables. It's also used for automatically generating the column/relationship 
 list on the client in the search dialog. So I won't have to make code 
 changes to the client when I alter the model on the server.

 perjantai, 5. syyskuuta 2014 17.13.10 UTC+3 Michael Bayer kirjoitti:

 well it’s not set to be mapped until after the setup part of it.   

 if you want to get every class whether mapped or not, maybe use 
 Base.__subclasses__() ?

 What’s the use case where you need the abstract base in the decl class 
 registry?  it’s not really something you’d want to refer to in a 
 relationship().



 On Sep 5, 2014, at 9:56 AM, Alex Grönholm alex.g...@nextday.fi wrote:

 Thanks. I've filed an issue 
 https://bitbucket.org/zzzeek/sqlalchemy/issue/3185/more-than-one-level-of-abstract-concrete
  
 at Bitbucket.

 A follow-up question: Why are abstract base classes not present in the 
 declarative class registry? Or is there another way to get all the mapped 
 classes besides iterating over Base._decl_class_registry?

 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to sqlalchemy+...@googlegroups.com.
 To post to this group, send email to sqlal...@googlegroups.com.
 Visit this group at http://groups.google.com/group/sqlalchemy.
 For more options, visit https://groups.google.com/d/optout.




-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


Re: [sqlalchemy] More than one level of abstract base classes doesn't work

2014-09-05 Thread Alex Grönholm
Sorry to be asking more questions, but the docs on inheritance don't get 
into much details on how the properties are supposed to work.
The following code produces unexpected results:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import AbstractConcreteBase, 
declarative_base

Base = declarative_base()


class Document(Base, AbstractConcreteBase):
doctype = Column('doc_type', Unicode, nullable=False)


class ActualDocument(Document):
__tablename__ = 'actual_documents'
__mapper_args__ = {'concrete': True, 'polymorphic_identity': 'actual'}

id = Column(Integer, primary_key=True)
name = Column('name_', Unicode)

configure_mappers()

for prop in class_mapper(Document).column_attrs:
print('%s (%s)' % (prop, prop.__class__.__name__))

for prop in class_mapper(ActualDocument).column_attrs:
print('%s (%s)' % (prop, prop.__class__.__name__))

Which gives me:

Document.doc_type (ColumnProperty)
Document.id (ColumnProperty)
Document.name_ (ColumnProperty)
Document.type (ColumnProperty)
ActualDocument.doctype (ColumnProperty)
ActualDocument.name (ColumnProperty)
ActualDocument.id (ColumnProperty)

I can understand Document.id (which comes from ActualDocument) and 
Document.type (which I assume is the polymorphic identity) but doc_type 
seems wrong to me. Why are doc_type and name_ not named doctype and name 
respectively, like they are on ActualDocument? Is this a bug? Am I right in 
guessing that the polymorphic union simply lacks the proper labels where 
the column name differs from the attribute name?

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


[sqlalchemy] More than one level of abstract base classes doesn't work

2014-09-04 Thread Alex Grönholm
The following code fails with AttributeError: 'NoneType' object has no 
attribute 'concrete':

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import AbstractConcreteBase, 
declarative_base

Base = declarative_base()


class Document(Base, AbstractConcreteBase):
type = Column(Unicode, nullable=False)


class ContactDocument(Document):
__abstract__ = True

send_method = Column('sendmethod', Unicode)


class ActualDocument(ContactDocument):
__tablename__ = 'actual_documents'
__mapper_args__ = {'concrete': True, 'polymorphic_identity': 'actual'}

id = Column(Integer, primary_key=True)

configure_mappers()


Am I not supposed to have more than one level of abstract base classes? Or 
am I doing something else wrong?
This is with SQLAlchemy 0.9.7.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


Re: [sqlalchemy] Encapsulating insert/update logic of mapped classes in the class itself

2014-06-02 Thread Alex Grönholm
That's the first thing I tried, but validators don't get called unless you 
explicitly set a value to the column.

So for something like session.add(DeliveryAddress()), the validator doesn't 
get called.

maanantai, 2. kesäkuuta 2014 14.27.47 UTC+3 Michael Bayer kirjoitti:


 On Jun 2, 2014, at 1:47 AM, Alex Grönholm alex.g...@nextday.fi 
 javascript: wrote: 

  This has been a problem for me for years. 
  
  class DeliveryAddress(Base, Address): 
  ... 
  delivery_method = Column(String) 
  ... 
  
  @event.listens_for(DeliveryAddress, 'before_insert') 
  def before_insert_deliveryaddress(mapper, connection, target): 
  settings = object_session(target).query(Settings).one() 
  target.delivery_method = settings.default_delivery_method 
  
  Is there absolutely no way to encapsulate this logic cleanly in the 
 actual class? 


 I use an attribute event for that, and more often just a simple 
 @validates.   

 @validates(“default_delivery_method”) 
 def _set_delivery_method(self, key, value): 
 self.settings.delivery_method = value 
 return value 





-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


Re: [sqlalchemy] Encapsulating insert/update logic of mapped classes in the class itself

2014-06-02 Thread Alex Grönholm

02.06.2014 16:44, Michael Bayer kirjoitti:
the ORM can't persist any value for delivery_method unless there is 
an actual attribute set event.


If you are saying session.add(DeliveryAddress()) and flushing, these 
are the options for deliveryaddress.delivery_method:


1. the value has no setting and is not present in the INSERT statement 
- it gets set as NULL in the DB.


2. the value has no setting, but you have a python or server side 
default set up on it.  At before_insert() time, that value is still 
None so that can't be what you're doing.


3. The DeliveryAddress() constructor sets delivery_method, so there's 
an attribute set event.


So I can only guess that you're looking for the None here? I guess 
there's some odd relationship to this Settings object such that it 
already exists in the DB with some other value such that you actually 
need to positively set None.  In any case, to have something 
happen upon DeliveryAddress(), you can either place that logic as part 
of __init__() (regular Python!) or if that bothers you, you can also 
set up the init() event for the DeliveryAddress class.
Settings is a singleton (just one row with ID 1). It contains the 
default values for a number of things.


I will have a look at __declare_last__, thanks!

That said, sometimes I need to react to inserts and insert other rows 
then. Attribute events won't help me there.
So far I've ended up making a module for these listeners and I just had 
a single listener for each event (before_insert or before_flush) with a 
lot of if..elif...branching.


If all of these options don't suit you and you absolutely insist on 
the before_insert event, it is very easy to add to your declarative 
base a mixin that sets these up for you (see 
http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/declarative.html#declare-last):


class BeforeInsertMixin(object):
@classmethod
def __declare_last__(cls):
if hasattr(cls, 'before_insert'):
event.listen(cls, 'before_insert', cls.before_insert)

Base = declarative_base(cls=BeforeInsertMixin)

class DeliveryAddress(Base):
# ...

@classmethod
def before_insert(cls, mapper, connection, target):
#...


if you want to change the signature, no problem:

class BeforeInsertMixin(object):
@classmethod
def __declare_last__(cls):
if hasattr(cls, 'before_insert'):
@event.listens_for(cls, 'before_insert')
def before_insert(mapper, connection, target):
target.before_insert(object_session(target))


class DeliveryAddress(Base):
# ...

def before_insert(self, session):
#...
These are frameworky types of hooks that SQLAlchemy would prefer to 
remain agnostic of, but it provides for you all the components you 
need to create whatever system of hooks you'd like.






On Jun 2, 2014, at 8:04 AM, Alex Grönholm alex.gronh...@nextday.fi 
mailto:alex.gronh...@nextday.fi wrote:


That's the first thing I tried, but validators don't get called 
unless you explicitly set a value to the column.


So for something like session.add(DeliveryAddress()), the validator 
doesn't get called.


maanantai, 2. kesäkuuta 2014 14.27.47 UTC+3 Michael Bayer kirjoitti:


On Jun 2, 2014, at 1:47 AM, Alex Grönholm alex.g...@nextday.fi
wrote:

 This has been a problem for me for years.

 class DeliveryAddress(Base, Address):
 ...
 delivery_method = Column(String)
 ...

 @event.listens_for(DeliveryAddress, 'before_insert')
 def before_insert_deliveryaddress(mapper, connection, target):
 settings = object_session(target).query(Settings).one()
 target.delivery_method = settings.default_delivery_method

 Is there absolutely no way to encapsulate this logic cleanly in
the actual class?


I use an attribute event for that, and more often just a simple
@validates.

@validates(default_delivery_method)
def _set_delivery_method(self, key, value):
self.settings.delivery_method = value
return value




--
You received this message because you are subscribed to the Google 
Groups sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, 
send an email tosqlalchemy+unsubscr...@googlegroups.com 
mailto:sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email tosqlalch...@googlegroups.com 
mailto:sqlalchemy@googlegroups.com.

Visit this group athttp://groups.google.com/group/sqlalchemy.
For more options, visithttps://groups.google.com/d/optout.


--
You received this message because you are subscribed to a topic in the 
Google Groups sqlalchemy group.
To unsubscribe from this topic, visit 
https://groups.google.com/d/topic/sqlalchemy/-s9GWB3hfso/unsubscribe.
To unsubscribe from this group and all its topics, send an email to 
sqlalchemy+unsubscr...@googlegroups.com 
mailto:sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com

[sqlalchemy] Encapsulating insert/update logic of mapped classes in the class itself

2014-06-01 Thread Alex Grönholm
This has been a problem for me for years.

class DeliveryAddress(Base, Address):
...
delivery_method = Column(String)
...

@event.listens_for(DeliveryAddress, 'before_insert')
def before_insert_deliveryaddress(mapper, connection, target):
settings = object_session(target).query(Settings).one()
target.delivery_method = settings.default_delivery_method

Is there absolutely no way to encapsulate this logic cleanly in the actual 
class?

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


[sqlalchemy] Mutable ARRAY

2014-05-03 Thread Alex Grönholm
There doesn't seem to be a class like MutableDict that provides equivalent 
functionality for the ARRAY column type. Any particular reason why? I'd 
like to be able to do .append() and .remove() on an array column. Do I have 
to roll my own?

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


Re: [sqlalchemy] Mutable ARRAY

2014-05-03 Thread Alex Grönholm

03.05.2014 16:04, Michael Bayer kirjoitti:
I'd like to provide mutablearray though, so if someone can roll it 
with some tests it can go right in.



I'll look into it.

Sent from my iPhone

On May 3, 2014, at 9:02 AM, Alex Grönholm alex.gronh...@nextday.fi 
mailto:alex.gronh...@nextday.fi wrote:


There doesn't seem to be a class like MutableDict that provides 
equivalent functionality for the ARRAY column type. Any particular 
reason why? I'd like to be able to do .append() and .remove() on an 
array column. Do I have to roll my own?

--
You received this message because you are subscribed to the Google 
Groups sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, 
send an email to sqlalchemy+unsubscr...@googlegroups.com 
mailto:sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com 
mailto:sqlalchemy@googlegroups.com.

Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the 
Google Groups sqlalchemy group.
To unsubscribe from this topic, visit 
https://groups.google.com/d/topic/sqlalchemy/QP4IBjzk9i8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to 
sqlalchemy+unsubscr...@googlegroups.com 
mailto:sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com 
mailto:sqlalchemy@googlegroups.com.

Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


[sqlalchemy] sqlacodegen 1.1.4 released.

2014-01-02 Thread Alex Grönholm
This release fixes compatibility with the just released SQLAlchemy 0.9.0 
final.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [sqlalchemy] How can I use the OVERLAPS operator?

2013-12-18 Thread Alex Grönholm
Ah, I was completely unaware of tuple_(). That's what I was looking for. 
Thanks!

keskiviikko, 18. joulukuuta 2013 18.31.42 UTC+2 Michael Bayer kirjoitti:


 On Dec 17, 2013, at 8:39 PM, Alex Grönholm 
 alex.g...@nextday.fijavascript: 
 wrote:

 I would like to check if two date ranges overlap. This is done using the 
 OVERLAPS 
 operatorhttp://www.postgresql.org/docs/9.2/static/functions-datetime.html
 .
 For example:

 SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS
(DATE '2001-10-30', DATE '2002-10-30');


 How do I do this in SQLAlchemy? I have no clue how to produce the 
 parentheses here.


 I think what we’re really looking at are two tuples, so might as well use 
 that:

  from sqlalchemy import create_engine, tuple_, select
  import datetime
  e = create_engine(postgresql://scott:tiger@localhost/test, 
 echo=True)
  s = select([
 ...   tuple_(datetime.date(2001, 2, 6), datetime.date(2001, 12, 
 21)).op('overlaps')(
 ...tuple_(datetime.date(2001, 10, 30), datetime.date(2002, 
 10, 30)))
 ...  ])
  e.scalar(s)
 2013-12-18 11:30:05,232 INFO sqlalchemy.engine.base.Engine SELECT 
 (%(param_1)s, %(param_2)s) overlaps (%(param_3)s, %(param_4)s) AS anon_1
 2013-12-18 11:30:05,232 INFO sqlalchemy.engine.base.Engine {'param_4': 
 datetime.date(2002, 10, 30), 'param_1': datetime.date(2001, 2, 6), 
 'param_3': datetime.date(2001, 10, 30), 'param_2': datetime.date(2001, 12, 
 21)}
 True






 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to sqlalchemy+...@googlegroups.com javascript:.
 To post to this group, send email to sqlal...@googlegroups.comjavascript:
 .
 Visit this group at http://groups.google.com/group/sqlalchemy.
 For more options, visit https://groups.google.com/groups/opt_out.




-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


[sqlalchemy] How can I use the OVERLAPS operator?

2013-12-17 Thread Alex Grönholm
I would like to check if two date ranges overlap. This is done using the 
OVERLAPS 
operator http://www.postgresql.org/docs/9.2/static/functions-datetime.html
.
For example:

SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS
   (DATE '2001-10-30', DATE '2002-10-30');


How do I do this in SQLAlchemy? I have no clue how to produce the 
parentheses here.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


[sqlalchemy] sqlacodegen 1.1.3 released.

2013-12-11 Thread Alex Grönholm
This release fixes compatibility with SQLAlchemy 0.8.3 and onwards. The 
test suite passes on SQLAlchemy 0.9.0b1 as well.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [sqlalchemy] Unit testing, mocking and dependency injection with SA Declarative.

2013-09-11 Thread Alex Grönholm
I wrote a blog post on this very topic recently: 
http://alextechrants.blogspot.fi/2013/08/unit-testing-sqlalchemy-apps.html


tiistai, 10. syyskuuta 2013 19.43.35 UTC+3 Toph Burns kirjoitti:

  Could you use an in-memory, sqlite db for your testing?  For our 
 applications, we have an initialization function that loads the database 
 connection strings from a config (.ini) file, passing those on to 
 create_engine.  In production it's a postgresql connection string, for 
 test, it's a sqlite:///:memory:'


   Toph Burns | Software Engineer
 5885 Hollis St.  Suite 100
 Emeryville, CA 94608
 510-597-4797
 bu...@amyris.com javascript:
   --
 *From:* sqlal...@googlegroups.com javascript: 
 [sqlal...@googlegroups.comjavascript:] 
 on behalf of Michel Albert [exh...@gmail.com javascript:]
 *Sent:* Tuesday, September 10, 2013 1:46 AM
 *To:* sqlal...@googlegroups.com javascript:
 *Subject:* [sqlalchemy] Unit testing, mocking and dependency injection 
 with SA Declarative.

   I am trying to wrap my head around how to do Dependency Injection with 
 SQLAlchemy and I am walking in circles. 

  I want to be able to mock out SA for most of my tests. I trust SA and 
 don't want to test serialisation into the DB. I just want to test my own 
 code. So I was thinking to do dependency injection, and mock out SA during 
 testing.

  But I don't know what to mock out, how and when to set up the session 
 properly, without doing it at the module level (which causes unwanted 
 side-effects only by importing the module).

  The only solution which comes to mind is to have one singleton which 
 deals with that. But that feels very unpythonic to me and I am wondering if 
 there's a better solution.

  I also saw that create_engine has an optional module kwarg, which I 
 could mock out. But then SA begins complaining that the return types are 
 not correct. And I don't want to specify return values for every possible 
 db-module call. That's way out of scope of my tests. I am not calling 
 anything on the db-module. That's SA's job, and, as said, I already trust 
 SA.

  Whenever I work on this I always run into the session_maker 
 initialisation as well. The examples to this on the module level, which I 
 really make me feel uneasy.

  Any tips? Just prodding myself in the right direction might help me out 
 enough.
  
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to sqlalchemy+...@googlegroups.com javascript:.
 To post to this group, send email to sqlal...@googlegroups.comjavascript:
 .
 Visit this group at http://groups.google.com/group/sqlalchemy.
 For more options, visit https://groups.google.com/groups/opt_out.
   

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


[sqlalchemy] How do I unregister event listeners?

2013-09-11 Thread Alex Grönholm
I'm trying to test code that listens to session events on all sessions. I 
can't pin it on any particular session or even sessionmaker due to the 
architecture of the software (sessions are explicitly instantiated on the 
fly).
All is well except that the listener sticks after the test is done, 
breaking test isolation. The ideal solution would be to unregister the 
listener in teardown(), but I don't see anything in the event API that 
could be used to do that.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


[sqlalchemy] Re: How do I unregister event listeners?

2013-09-11 Thread Alex Grönholm
There seems to be an undocumented function named remove() in the 
sqlalchemy.event module that looks like what I want, but it doesn't work:

Traceback (most recent call last):
  File 
/home/alex/virtualenv/triancore/lib/python3.3/site-packages/nose/case.py, 
line 198, in runTest
self.test(*self.arg)
  File /home/alex/workspace/TrianCore/tests/rpc/test_eventpublisher.py, 
line 36, in test_stop_publisher
self.publisher.stop()
  File /home/alex/workspace/TrianCore/trian/core/rpc/eventpublisher.py, 
line 62, in stop
event.remove(Session, 'after_flush', self.queue_events)
  File 
/home/alex/virtualenv/triancore/lib/python3.3/site-packages/sqlalchemy/event.py,
 
line 76, in remove
for tgt in evt_cls._accept_with(target):
nose.proxy.TypeError: 'type' object is not iterable

keskiviikko, 11. syyskuuta 2013 20.16.49 UTC+3 Alex Grönholm kirjoitti:

 I'm trying to test code that listens to session events on all sessions. I 
 can't pin it on any particular session or even sessionmaker due to the 
 architecture of the software (sessions are explicitly instantiated on the 
 fly).
 All is well except that the listener sticks after the test is done, 
 breaking test isolation. The ideal solution would be to unregister the 
 listener in teardown(), but I don't see anything in the event API that 
 could be used to do that.


-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [sqlalchemy] How do I unregister event listeners?

2013-09-11 Thread Alex Grönholm
Thanks, I'll try to make it work with the latter method somehow. Clearing 
all session event listeners is not an option because some of the code under 
test relies on a permanent listener being there.

keskiviikko, 11. syyskuuta 2013 21.15.46 UTC+3 Michael Bayer kirjoitti:

 you can either remove all the listeners for a certain type, like this:

 events.MapperEvents._clear()

 the other alternative is wrap your events with a set that you control:

 my_listeners = set()

 @event.listens_for(target, whatever)
 def evt(target):
for listener in my_listeners:
 listener(target)



 On Sep 11, 2013, at 1:44 PM, Alex Grönholm 
 alex.g...@nextday.fijavascript: 
 wrote:

 Thanks for the quick reply. I don't want to use prerelease versions of 
 SQLAlchemy though. Is there any recommended way of doing this in 0.8.2?

 keskiviikko, 11. syyskuuta 2013 20.40.40 UTC+3 Michael Bayer kirjoitti:


 On Sep 11, 2013, at 1:16 PM, Alex Grönholm alex.g...@nextday.fi wrote: 

  I'm trying to test code that listens to session events on all sessions. 
 I can't pin it on any particular session or even sessionmaker due to the 
 architecture of the software (sessions are explicitly instantiated on the 
 fly). 
  All is well except that the listener sticks after the test is done, 
 breaking test isolation. The ideal solution would be to unregister the 
 listener in teardown(), but I don't see anything in the event API that 
 could be used to do that. 

 the public API is in 0.9 (of course there are crude hacks in 0.8) :  
 http://docs.sqlalchemy.org/en/latest/changelog/migration_09.html#event-removal-api
  



 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to sqlalchemy+...@googlegroups.com javascript:.
 To post to this group, send email to sqlal...@googlegroups.comjavascript:
 .
 Visit this group at http://groups.google.com/group/sqlalchemy.
 For more options, visit https://groups.google.com/groups/opt_out.




-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


[sqlalchemy] sqlacodegen 1.1.2 released

2013-09-01 Thread Alex Grönholm
This is another bugfix release. All reported issues have now been resolved.
Changes in this version:

   - Fixed non-default schema name not being present in __table_args__ 
   (fixes #2)
   - Fixed self referential foreign key causing column type to not be 
   rendered
   - Fixed missing deferrable and initially keyword arguments in 
   ForeignKey constructs
   - Fixed foreign key and check constraint handling with alternate schemas 
   (fixes #3)
   

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


[sqlalchemy] sqlacodegen 1.1.1 released

2013-06-12 Thread Alex Grönholm
This is a bugfix release. Issues resolved:

   - Fixed TypeError when inflect could not determine the singular name of 
   a table for a many-to-1 relationship
   - Fixed _IntegerType, _StringType etc. being rendered instead of proper 
   types on MySQL
   

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[sqlalchemy] sqlacodegen 1.1.0 released

2013-05-25 Thread Alex Grönholm
Although it's only been a week since the initial release, I've already 
added a bunch of new features.
Release highlights:

   - Added automatic detection of joined-table inheritance
   - Fixed missing class name prefix in primary/secondary joins in 
   relationships
   - Instead of wildcard imports, generate explicit imports dynamically
   - Use the inflect library to produce better guesses for table to class 
   name conversion
   - Automatically detect Boolean (and Enum) columns based on 
   CheckConstraints
   - Skip redundant CheckConstraints for Enum and Boolean columns
   

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[sqlalchemy] What is polymorphic_on needed for in a joined table inheritance schema?

2013-05-24 Thread Alex Grönholm
I used joined table inheritance in Hibernate and it worked fine without any 
extra discriminator columns. Why is it necessary in SQLAlchemy?
I can understand the need for such a column in single table inheritance, 
but not joined table.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] Announcing new model code generation tool: sqlacodegen

2013-05-18 Thread Alex Grönholm

18.05.2013 12:35, Chris Withers kirjoitti:

On 18/05/2013 01:28, Alex Grönholm wrote:

This is a tool that reads the structure of an existing database and
generates the appropriate SQLAlchemy model code, using the declarative
style if possible.


Playing devils advocate to get my head around this: why would you want 
to generate code when you could just reflect the models?


Chris


I can think of a number of reasons:

 * You'll have to write the classes manually otherwise (save for the
   column defs if you use reflection)
 * Reflection won't give you relationships -- you'd have to add them
   manually anyway
 * Reflection takes time and will slow down application startup,
   especially with large schemas
 * Automatic generation of schema migration scripts will not work
   unless you have a model that differs from the actual schema
 * You may need static analysis of the code

The more complex your schema is, the more useful automatic code 
generation will be for you. Of course, if you only do metadata 
reflection and don't use declarative, well, that's another matter. But 
most people want mapped classes to use in their apps.


--
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[sqlalchemy] Announcing new model code generation tool: sqlacodegen

2013-05-17 Thread Alex Grönholm
After a while of trying to fix sqlautocode, I ended up writing a new tool 
instead.

Copypasta from the README:
-

This is a tool that reads the structure of an existing database and 
generates the appropriate SQLAlchemy model code, using the declarative 
style if possible.
Features 
   
   - Supports SQLAlchemy 0.6.x - 0.8.x
   - Produces declarative code that almost looks like it was hand written
   - Produces PEP 8 http://www.python.org/dev/peps/pep-0008/ compliant 
   code
   - Accurately determines relationships, including many-to-many, one-to-one
   - Excellent test coverage

-
It should work at least as well as sqlautocode. There is some room for 
future improvement, of course:

   - Autodetection of joined-table inheritance
   - Code generation for separate tables/classes/mappers instead of 
   declarative
   - Proper code generation for deferred/immediate foreign key constraints
   - Sorting out problems with CheckConstraints (there seems to be a 
   problem outside of sqlacodegen here)
   

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[sqlalchemy] Re: Announcing new model code generation tool: sqlacodegen

2013-05-17 Thread Alex Grönholm
Forgot to add the link: https://pypi.python.org/pypi/sqlacodegen

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[sqlalchemy] Enum recipe on SQLAlchemy 0.8.0 final

2013-04-10 Thread Alex Grönholm
The following class works on 0.8.0b2 but not 0.8.0 final:
 

 class EnumWrapper(SchemaType, TypeDecorator):
 def __init__(self, cls):
 kwargs = {'name': cls.__name__.lower()}
 self.impl = Enum(*(obj.key for obj in cls.values), **kwargs)
 self.wrapped = cls

 def _set_table(self, table, column):
 self.impl._set_table(table, column)

 def process_bind_param(self, value, dialect):
 if value is None:
 return None
 if isinstance(value, self.wrapped):
 return value.key
 elif isinstance(value, str):
 if value not in self.wrapped.symbols:
 raise TypeError('No such enum value in %s: %s' % 
 (self.wrapped.__name__, value))
 return value
 raise TypeError('Expected %s, got %s instead' % (self.wrapped, 
 type(value)))

 def process_result_value(self, value, dialect):
 return getattr(self.wrapped, value) if value is not None else None


The error message (TypeError: __init__() got an unexpected keyword 
argument 'schema') originates from types.py, line 1886.
Is inheriting from SchemaType still necessary? That is what seems to break 
things on 0.8.0 final.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] Enum recipe on SQLAlchemy 0.8.0 final

2013-04-10 Thread Alex Grönholm

10.04.2013 18:06, Michael Bayer kirjoitti:


On Apr 10, 2013, at 5:10 AM, Alex Grönholm alex.gronh...@nextday.fi 
mailto:alex.gronh...@nextday.fi wrote:



The following class works on 0.8.0b2 but not 0.8.0 final:

class EnumWrapper(SchemaType, TypeDecorator):
def __init__(self, cls):
kwargs = {'name': cls.__name__.lower()}
self.impl = Enum(*(obj.key for obj in cls.values), **kwargs)
self.wrapped = cls

def _set_table(self, table, column):
self.impl._set_table(table, column)

def process_bind_param(self, value, dialect):
if value is None:
return None
if isinstance(value, self.wrapped):
return value.key
elif isinstance(value, str):
if value not in self.wrapped.symbols:
raise TypeError('No such enum value in %s: %s' %
(self.wrapped.__name__, value))
return value
raise TypeError('Expected %s, got %s instead' %
(self.wrapped, type(value)))

def process_result_value(self, value, dialect):
return getattr(self.wrapped, value) if value is not None
else None


The error message (TypeError: __init__() got an unexpected keyword 
argument 'schema') originates from types.py, line 1886.
Is inheriting from SchemaType still necessary? That is what seems to 
break things on 0.8.0 final.


Line 1886 of types.py, both in 0.8.0 and in tip, is this:

t.drop(bind=bind, checkfirst=checkfirst)

so that doesn't seem like the line we're referring to.


My bad, it was line 1866: return impltype(name=self.name, ...)
Since your example lacks context, I had to modify the call to Enum 
to use a series of string names (don't know what obj.key, cls.values 
refer to).  From there, I managed to get a stack trace that refers to 
line 1863 of types.py.


In the documentation for TypeDecorator at 
http://docs.sqlalchemy.org/en/rel_0_8/core/types.html#sqlalchemy.types.TypeDecorator, 
the example includes a copy() method.   There is also a copy() method 
in the original Enum recipe on my blog at 
http://techspot.zzzeek.org/files/2011/decl_enum.py.


If the constructor of your decorated type is not compatible with the 
type you're wrapping, you need to provide copy() as well:


def copy(self):
return DeclEnumType(self.wrapped)
Yet, the error goes away once I add something like that. Strange though, 
everything worked fine even without a copy() method in 0.8.0b2.


Thanks!



hope this helps !


--
You received this message because you are subscribed to a topic in the 
Google Groups sqlalchemy group.
To unsubscribe from this topic, visit 
https://groups.google.com/d/topic/sqlalchemy/LE-EIznAIT4/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to 
sqlalchemy+unsubscr...@googlegroups.com.

To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




--
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] CircularDependencyError with relationships

2012-06-06 Thread Alex Grönholm

06.06.2012 18:06, Michael Bayer kirjoitti:
you need to use the post_update option described at 
http://docs.sqlalchemy.org/en/rel_0_7/orm/relationships.html#rows-that-point-to-themselves-mutually-dependent-rows 
.

Thanks for the pointer. Problem solved :)


On Jun 6, 2012, at 1:15 AM, Alex Grönholm wrote:

I have trouble configuring two relationships from one class to 
another. The following code should be fairly self-explanatory:



from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base


Base = declarative_base()

class Company(Base):
__tablename__ = 'companies'
id = Column(Integer, primary_key=True)
default_address_id = Column(Integer, ForeignKey('addresses.id', 
use_alter=True, name='defaultaddress_fk'))
addresses = relationship('Address', backref='company', 
primaryjoin='Address.company_id == Company.id')
default_address = relationship('Address', 
primaryjoin='Company.default_address_id == Address.id')



class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
company_id = Column(Integer, ForeignKey(Company.id), nullable=False)


engine = create_engine('sqlite:///', echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
company = Company()
address = Address()
session.add(company)
company.default_address = address
company.addresses.append(address)
session.flush()


What I expect is SQLAlchemy to 1) create the company, 2) create the 
address with the new company's id in company_id, 3) assign the ID of 
the new address to company.default_address_id

Trouble is, I get this error:

sqlalchemy.exc.CircularDependencyError: Circular dependency detected. 
Cycles: set([ProcessState(ManyToOneDP(Company.default_address), 
Company at 0x16a7210, delete=False), 
ProcessState(ManyToOneDP(Address.company), Address at 0x16ad190, 
delete=False), SaveUpdateState(Company at 0x16a7210), 
ProcessState(OneToManyDP(Company.addresses), Company at 0x16a7210, 
delete=False), SaveUpdateState(Address at 0x16ad190)]) all edges: 
set([(ProcessState(OneToManyDP(Company.addresses), Company at 
0x16a7210, delete=False), SaveUpdateState(Address at 0x16ad190)), 
(SaveUpdateState(Address at 0x16ad190), 
ProcessState(ManyToOneDP(Company.default_address), Company at 
0x16a7210, delete=False)), (SaveUpdateState(Company at 0x16a7210), 
SaveUpdateState(Address at 0x16ad190)), (SaveUpdateState(Company 
at 0x16a7210), ProcessState(ManyToOneDP(Address.company), Address 
at 0x16ad190, delete=False)), 
(ProcessState(ManyToOneDP(Company.default_address), Company at 
0x16a7210, delete=False), SaveUpdateState(Company at 0x16a7210)), 
(ProcessState(ManyToOneDP(Address.company), Address at 0x16ad190, 
delete=False), SaveUpdateState(Address at 0x16ad190)), 
(SaveUpdateState(Company at 0x16a7210), 
ProcessState(OneToManyDP(Company.addresses), Company at 0x16a7210, 
delete=False))])


What am I doing wrong? I had a similar problem in my production app 
when trying to delete a Company that had a default address assigned.

I'm on SQLAlchemy 0.7.7.

--
You received this message because you are subscribed to the Google 
Groups sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/fqFKTLBdTYwJ.
To post to this group, send email to sqlalchemy@googlegroups.com 
mailto:sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com 
mailto:sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.


--
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.


--
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] CircularDependencyError with relationships

2012-06-05 Thread Alex Grönholm
I have trouble configuring two relationships from one class to another. The 
following code should be fairly self-explanatory:


from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base


Base = declarative_base()

class Company(Base):
__tablename__ = 'companies'
id = Column(Integer, primary_key=True)
default_address_id = Column(Integer, ForeignKey('addresses.id', 
use_alter=True, name='defaultaddress_fk'))
addresses = relationship('Address', backref='company', 
primaryjoin='Address.company_id == Company.id')
default_address = relationship('Address', 
primaryjoin='Company.default_address_id == Address.id')


class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
company_id = Column(Integer, ForeignKey(Company.id), nullable=False)


engine = create_engine('sqlite:///', echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
company = Company()
address = Address()
session.add(company)
company.default_address = address
company.addresses.append(address)
session.flush()


What I expect is SQLAlchemy to 1) create the company, 2) create the address 
with the new company's id in company_id, 3) assign the ID of the new 
address to company.default_address_id
Trouble is, I get this error:

sqlalchemy.exc.CircularDependencyError: Circular dependency detected. 
Cycles: set([ProcessState(ManyToOneDP(Company.default_address), Company at 
0x16a7210, delete=False), ProcessState(ManyToOneDP(Address.company), 
Address at 0x16ad190, delete=False), SaveUpdateState(Company at 
0x16a7210), ProcessState(OneToManyDP(Company.addresses), Company at 
0x16a7210, delete=False), SaveUpdateState(Address at 0x16ad190)]) all 
edges: set([(ProcessState(OneToManyDP(Company.addresses), Company at 
0x16a7210, delete=False), SaveUpdateState(Address at 0x16ad190)), 
(SaveUpdateState(Address at 0x16ad190), 
ProcessState(ManyToOneDP(Company.default_address), Company at 0x16a7210, 
delete=False)), (SaveUpdateState(Company at 0x16a7210), 
SaveUpdateState(Address at 0x16ad190)), (SaveUpdateState(Company at 
0x16a7210), ProcessState(ManyToOneDP(Address.company), Address at 
0x16ad190, delete=False)), 
(ProcessState(ManyToOneDP(Company.default_address), Company at 0x16a7210, 
delete=False), SaveUpdateState(Company at 0x16a7210)), 
(ProcessState(ManyToOneDP(Address.company), Address at 0x16ad190, 
delete=False), SaveUpdateState(Address at 0x16ad190)), 
(SaveUpdateState(Company at 0x16a7210), 
ProcessState(OneToManyDP(Company.addresses), Company at 0x16a7210, 
delete=False))])

What am I doing wrong? I had a similar problem in my production app when 
trying to delete a Company that had a default address assigned.
I'm on SQLAlchemy 0.7.7.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/fqFKTLBdTYwJ.
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.



Re: [sqlalchemy] Re: Unpickling of model instances fails when using mapped collections

2012-02-16 Thread Alex Grönholm
Yup, this is exactly what I did just 2 minutes ago :)

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/Eto2-sirT7wJ.
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] Persisting an object with cascading relationships

2011-11-18 Thread Alex Grönholm
My use case is the following: each SalesItem requires a calcPriceList and a 
salesPriceList (of type PriceList) attached to it.
For that, SalesItem has two fields:
calcpricelist_id = Column(BigInteger, ForeignKey(PriceList.id), 
nullable=False)
salespricelist_id = Column(BigInteger, ForeignKey(PriceList.id), 
nullable=False)
It also has two relationships:
calcPriceList = relationship(PriceList, primaryjoin=calcpricelist_id == 
PriceList.id, cascade='save-update,delete')
salesPriceList = relationship(PriceList, primaryjoin=salespricelist_id 
== PriceList.id, cascade='save-update')

Now I have a problem -- I want to create a new SalesItem. I want to 
minimize the hassle so I set up a before_insert mapper listener (and 
verified it's being called) that attaches transient PriceList instances to 
said relationships.
What I expected the session to do during flush is to insert these two 
PriceLists into the database, fill in the calcpricelist_id and 
salespricelist_id fields on SalesItem before attempting to insert the 
SalesItem itself.
This is however not happening and it's trying to insert the SalesItem 
first, resulting in an IntegrityError.

Is what I am trying to do wrong? Should I just give up trying to do this in 
an event listener?

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/dUchvgtL1mkJ.
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.



Re: [sqlalchemy] Persisting an object with cascading relationships

2011-11-18 Thread Alex Grönholm
How silly of me not to have checked that in the docs. Rather embarrassing 
really :) Thanks.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/rTk1ea1hvrgJ.
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.



Re: [sqlalchemy] Single table inheritance + join weirdness

2011-11-16 Thread Alex Grönholm
Yeah my bad, the original query does indeed query for (Z.id, B.name). I had 
just changed it to A.name to get the printout for the workaround query 
and forgot to change it back before pasting here.
If there's something I can do to contribute (not sure I'm qualified to 
write those tests), do tell.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/lGxM13xQhu8J.
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] Single table inheritance + join weirdness

2011-11-15 Thread Alex Grönholm
I encountered a little strangeness when joining to a class using single 
table inheritance.
I was wondering why I got no results for one particular query.
This was originally encountered with PostgreSQL but was successfully 
reproduced with SQLite.
Is this a bug or a user error?
SNIPSNIP

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.engine import create_engine
from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.types import Integer, Unicode
from sqlalchemy.orm.session import Session
from sqlalchemy.orm import relationship


Base = declarative_base(create_engine('sqlite:///'))

class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
disc = Column(Unicode, nullable=False)
name = Column(Unicode)

__mapper_args__ = {'polymorphic_on': disc}


class B(A):
__mapper_args__ = {'polymorphic_identity': 'b'}


class Z(Base):
__tablename__ = 'z'
id = Column(Integer, primary_key=True)
b_id = Column(Integer, ForeignKey(B.id))

b = relationship(B)

Base.metadata.create_all()
session = Session()
query = session.query(Z, A.name).outerjoin(Z.b).filter(Z.id == 1)
print query

#SELECT z.id AS z_id, z.b_id AS z_b_id, a.name AS a_name 
#FROM z LEFT OUTER JOIN a ON a.id = z.b_id AND a.disc IN (?) 
#WHERE z.id = ? AND a.disc IN (?)
#   ^- why is this condition here?
#
# WORKAROUND: 
# query = session.query(Z, A.name).outerjoin(Z.b).filter(Z.id == 1)
#  ^- use the superclass instead
#
#SELECT z.id AS z_id, z.b_id AS z_b_id, a.name AS a_name 
#FROM z LEFT OUTER JOIN a ON a.id = z.b_id AND a.disc IN (?) 
#WHERE z.id = ?
# ^- no extra WHERE condition this time around

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/RB_1UbBZRogJ.
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] Vs: Composite Foreign Key with ondelete='CASCADE' does not work on mysql

2011-05-30 Thread Alex Grönholm
It's not clear from your code, but are you using InnoDB or MyISAM? You need 
to be using InnoDB for foreign keys to work properly.

-- 
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.