[sqlalchemy] Re: relationships for no-table-related Class

2010-11-17 Thread neurino
Thanks Michael,

this solved most of my doubts.

Greetings
neurino

On Nov 16, 5:51 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 On Nov 16, 2010, at 4:19 AM, neurino wrote:





  I didn't mean mapping Root to a Table (if not necessary) is my intent,
  what I'd like to know is how to get the same behavior without the
  bloat of an extra table.

  make your application work a certain way (where certain way here is not 
  clear)

  I make an example, maybe I'm wrong tho:

  let's say I delete an item, I'd expect not to find this item anymore
  in its (ex) parent items

  subarea.items
  [item]
  session.delete(subarea.items[0])
  session.commit()
  subarea.items
  []

  This would be not the same for root's areas if I just use a query

  root.areas = query(Area).all()
  root.areas
  [area]
  session.delete(root.areas[0])
  session.commit()
  root.items
  [area]

  I hope I has been able to focus on my question now.

 right so I'd just make the attribute live:

 Session = scoped_session(sessionmaker())

 class Root(object):
   �...@property
    def areas(self):
         return Session.query(Area).all()

 singleton_root = Root()

 class Area(object):
    parent = singleton_root

 This is no different than the example above - 
 Session.delete(someobject.collection[someindex]) does not remove the item 
 from the collection - its only because of the call to commit() that 
 someobject.collection is expired, and is then reloaded.

 If you'd like to later add caching to Root.areas such that the collection is 
 pulled from memory until Session.commit() is called, you could enhance 
 Root.areas to maintain values in a cache, such as a WeakKeyDictionary which 
 uses Session().transaction as the key.





  Thanks for your help
  neurino

  On Nov 15, 9:57 pm, Michael Bayer mike...@zzzcomputing.com wrote:
  On Nov 15, 2010, at 10:46 AM, neurino wrote:

  Thanks for your answer first.

  Root is a singleton, its class is not mapped to a table.

  What I mean is I could add a table roots to the database with a
  sigle row and add areas a foreign key root_id and create a
  relationship as from subareas with parent area and get what I'm
  talking about.

  sure, then you're mapping Root to a table, and having just one row.   That 
  would make Root.area act exactly like a relationship() though its a little 
  strange to have a row in the database just to make your application work a 
  certain way (where certain way here is not clear).

  This relationship, between root and area, as long as areas and
  subareas would come in handy for example to traverse the tree for
  extracting an xml simply, or to make recursive calculations.

  Before sqlalchemy I was used to add all areas, subareas, items, parent
  attributes to classes by myself but now I'm in the situation that 80%
  of the work is done by sqlalchemy automatically and I'm not sure how
  to fill the remaining, possibly having both areas and subareas behave
  at the same way to avoid confusion (just as an example, lazy loading).

  Thanks for your support
  neurino

  On Nov 15, 3:49 pm, Michael Bayer mike...@zzzcomputing.com wrote:
  On Nov 15, 2010, at 8:06 AM, neurino wrote:

  So no advice?

  Are relationships and backref something more than attributes I can
  setup with a query?

  Thank you for your support.

  what's not stated clearly here is what Root is.  If that's not a class 
  mapped to a table, then you'd just need to use regular Python attributes 
  and descriptors to establish the in-python behavior you're looking for.  
  Seems like its essentially some kind of query object, so your 
  query.all()/.parent = some_root approach is what you'd go with, though 
  it would appear that Root is a singleton anyway, meaning this could be 
  established on Area at the class level instead of assigning to each 
  instance.

  Its not clear what other behavior of relationship() would apply here, 
  since Root has no database identity.

  On Nov 11, 9:45 am, neurino neur...@gmail.com wrote:
  I have a tree structure

  Root
    |
    +--Area
    |    |
    |    +--SubArea
    |    |    |
    |    |    +--Item
    |    |    |
    |    |    +--Item
    |    |
    |    +--SubArea
    |         |
    |         +--Item
    |         |
    |         +--Item
    |
    +--Area
         |
         +--SubArea
         |    |
         |    +--Item
         |    |
         |    +--Item
         |
         +--SubArea
              |
              +--Item
              |
              +--Item

  The tree structure corresponds to slqalchemy db tables `areas`,
  `subareas` and `items`.

  Something like this:

      mapper(Area, areas_table, properties={
          'subareas': relationship(SubArea, backref='parent'),
          })
      mapper(SubArea, subareas__table, properties={
          'items': relationship(Item, backref='parent'),
          })
      mapper(Item, items_table)

  so each Area instance will have a `subareas` list and each SubArea
  will have a `items` 

Re: [sqlalchemy] order_by: ArgumentError

2010-11-17 Thread Enrico Morelli
On Tue, 16 Nov 2010 11:37:12 -0500
Michael Bayer mike...@zzzcomputing.com wrote:

 
 On Nov 16, 2010, at 6:16 AM, Enrico Morelli wrote:
 
  On Mon, 15 Nov 2010 15:56:06 -0500
  Michael Bayer mike...@zzzcomputing.com wrote:
  
  its looking for a Column object.menus_table.c.weight instead of
  'weight'.
  
  
  Thanks, I modified the query:
  main_menu = Session.query(Menu).filter(and_(Menu.parent_id==None,
  Menu.lang==session['lang'])).order_by(menus_table.c.weight.asc()).all()
  
  but the error is the same:
  
  ArgumentError: Column-based expression object expected for argument
  'order_by'; got: 'weight', type type 'str'
 
 no , the mapping:
 
 mapper(Menu, menus_table,
  properties={
  'children': relation(Menu, order_by=menus_table.c.weight),
  'permissions': relation(Permissions, backref='menus',
  secondary=menus_permissions_table)
  })
 
 

Thank you very much.

-- 
---
   (o_
(o_//\  Coltivate Linux che tanto Windows si pianta da solo.
(/)_   V_/_
+--+
| ENRICO MORELLI |  email: more...@cerm.unifi.it   |
| * *   *   *|  phone: +39 055 4574269 |
|  University of Florence|  fax  : +39 055 4574253 |
|  CERM - via Sacconi, 6 -  50019 Sesto Fiorentino (FI) - ITALY|
+--+

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



[sqlalchemy] TIMEDIFF and SQLAlchemy

2010-11-17 Thread Christian Démolis
Hi,

Do you know how to do this query with sqlalchemy?

*SELECT
Id,  TIMEDIFF( End, Start)
FROM
plage
WHERE
TIMEDIFF(End,Start)=TIME('02:20:00');*

In my model, Start and End are DateTime
Start = Column('Start', DateTime)
End = Column('End', DateTime)

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



Re: [sqlalchemy] TIMEDIFF and SQLAlchemy

2010-11-17 Thread akm
Try this:

from sqlalchemy import func
from sqlalchemy.sql import select

s = select( [Plage.Id,
func.timediff(Plage.Start, Plage.Start)
],
   (func.timediff(Plage.Start, Plage.Start) = func.time('02:20:00'))
   )


Thanks,
--
Abdul Kader M

On Wed, Nov 17, 2010 at 4:36 PM, Christian Démolis
christiandemo...@gmail.com wrote:
 Hi,

 Do you know how to do this query with sqlalchemy?

 SELECT
 Id,  TIMEDIFF( End, Start)
 FROM
 plage
 WHERE
 TIMEDIFF(End,Start)=TIME('02:20:00');

 In my model, Start and End are DateTime
 Start = Column('Start', DateTime)
 End = Column('End', DateTime)

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


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



Re: [sqlalchemy] declarative one to many relationship with composite primary key

2010-11-17 Thread Adrien Saladin
On Wed, Nov 17, 2010 at 1:16 AM, Michael Bayer mike...@zzzcomputing.com wrote:
 ForeignKeyConstraint needs to go into __table_args__ when using declarative.

 http://www.sqlalchemy.org/docs/orm/extensions/declarative.html#table-configuration

Thanks for the note. I have updated my test script to use
__table_args__  but the error remains the same (see script and ouput
below).

I then tried with the hybrid approach
(http://www.sqlalchemy.org/docs/orm/extensions/declarative.html#using-a-hybrid-approach-with-table)
which works well.
Am I again doing something wrong with declarative ?

Thanks,


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


Base = declarative_base()

class Foo(Base):
   __tablename__ = foo
   one = Column(Integer, primary_key=True)
   two = Column(Integer, primary_key=True)

class Bar(Base):
   __tablename__ = bar
   __table_args__ = (  ForeignKeyConstraint(['one_id', 'two_id'],
['foo.one', 'foo.two']) )
   id = Column(Integer, primary_key=True)
   one_id = Column(Integer, nullable=False)
   two_id = Column(Integer, nullable=False)

   foo = relationship(Foo, backref = bars)



metadata = Base.metadata

engine = create_engine('sqlite:///:memory:', echo=True)
metadata.create_all(engine)

from sqlalchemy.orm import sessionmaker

# create a configured Session class
Session = sessionmaker(bind=engine)

# create a Session
session = Session()

foo = Foo()
foo.one = 1
foo.two = 2
session.add(foo)
session.commit()

#



2010-11-17 14:56:01,309 INFO sqlalchemy.engine.base.Engine.0x...9690
PRAGMA table_info(foo)
2010-11-17 14:56:01,309 INFO sqlalchemy.engine.base.Engine.0x...9690 ()
2010-11-17 14:56:01,310 INFO sqlalchemy.engine.base.Engine.0x...9690
PRAGMA table_info(bar)
2010-11-17 14:56:01,310 INFO sqlalchemy.engine.base.Engine.0x...9690 ()
2010-11-17 14:56:01,310 INFO sqlalchemy.engine.base.Engine.0x...9690
CREATE TABLE foo (
one INTEGER NOT NULL,
two INTEGER NOT NULL,
PRIMARY KEY (one, two)
)


2010-11-17 14:56:01,310 INFO sqlalchemy.engine.base.Engine.0x...9690 ()
2010-11-17 14:56:01,310 INFO sqlalchemy.engine.base.Engine.0x...9690 COMMIT
2010-11-17 14:56:01,311 INFO sqlalchemy.engine.base.Engine.0x...9690
CREATE TABLE bar (
id INTEGER NOT NULL,
one_id INTEGER NOT NULL,
two_id INTEGER NOT NULL,
PRIMARY KEY (id)
)


2010-11-17 14:56:01,311 INFO sqlalchemy.engine.base.Engine.0x...9690 ()
2010-11-17 14:56:01,311 INFO sqlalchemy.engine.base.Engine.0x...9690 COMMIT
Traceback (most recent call last):
  File compositePrimaryKey_decl.py, line 39, in module
foo = Foo()
  File string, line 4, in __init__
  File 
/home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/state.py,
line 93, in initialize_instance
fn(self, instance, args, kwargs)
  File 
/home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/mapper.py,
line 2357, in _event_on_init
instrumenting_mapper.compile()
  File 
/home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/mapper.py,
line 805, in compile
mapper._post_configure_properties()
  File 
/home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/mapper.py,
line 834, in _post_configure_properties
prop.init()
  File 
/home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/interfaces.py,
line 493, in init
self.do_init()
  File 
/home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/properties.py,
line 840, in do_init
self._determine_joins()
  File 
/home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/properties.py,
line 969, in _determine_joins
% self)
sqlalchemy.exc.ArgumentError: Could not determine join condition
between parent/child tables on relationship Bar.foo.  Specify a
'primaryjoin' expression.  If this is a many-to-many relationship,
'secondaryjoin' is needed as well.


The script below works with the hybrid declarative approach:

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


Base = declarative_base()

class Foo(Base):
   __tablename__ = foo
   one = Column(Integer, primary_key=True)
   two = Column(Integer, primary_key=True)



bartable = Table(bar, Base.metadata,
   Column(id, Integer, primary_key=True),
   Column(one_id, Integer, nullable=False),
   Column(two_id, Integer, nullable=False),
   ForeignKeyConstraint(['one_id', 'two_id'], ['foo.one', 'foo.two']),
)




class Bar(Base):
   __table__ = bartable
   foo = relationship(Foo, backref = bars)


metadata = Base.metadata

engine = create_engine('sqlite:///:memory:', echo=True)
metadata.create_all(engine)

from sqlalchemy.orm import sessionmaker

# create a configured Session class
Session = sessionmaker(bind=engine)

# create a Session
session = Session()

foo = Foo()
foo.one = 1
foo.two = 2

[sqlalchemy] Encoding issue with SqlAlchemy + cxOracle

2010-11-17 Thread Guilherme Menezes
Hi,

I am having an encoding issue using Python 2.6.2, SqlAlchemy 0.6.5 and
cxOracle 5.0.4 to access an Oracle 11g database.

I am using the NLS_LANG=.AL32UTF8 enviroment variable. My table in
Oracle is correctly configured to accept Unicode.

First, I compiled cxOracle without the WITH_UNICODE flag (as
recommended by SqlAlchemy).  I was passing data to SqlAlchemy as
unicode() objects. Everything worked without errors or warnings.

However, sometimes Oracle would complain that the string I was trying
to insert into a VARCHAR2 field was too big ( 4000), even when the
string size ( len(the_string.encode('utf-8')) ) was about 2300 bytes
(before SqlAlchemy). I used a sniffer to verify that the Oracle client
was sending two bytes for each character (even the ASCII ones),
instead of sending two bytes only for special characters.

I repeated this insertion experiment using cx_Oracle directly and
passing unicode() objects to it. Same thing: no errors or warnings,
and again the sniffer shown that the Oracle client was sending two
bytes per character. It seemed to me that cx_Oracle does not really
supports unicode() objects; it accepts them but it does not encode()
them to the correct encoding (as set in NLS_LANG variable).

However, when reading data from Oracle everything worked as expected
(i.e. someone was converting the UTF-16(?) string to UTF-8, probably
Oracle itself).

I tried two approaches to make the Oracle client send data in UTF-8
(not UTF-16):

1. Passing str() objects to SqlAlchemy. SqlAlchemy would then complain
in a warning:
* UnicodeWarning: Unicode equal comparison failed to convert both
arguments to Unicode - interpreting them as being unequal *
It worked, but it did not seem right, since I was receiving unicode()
objects and sending str() objetcs to SqlAlchemy. Moreover, I did not
know how things work inside SqlAlchemy, so I tried something else.

2. Compiling cx_Oracle with the WITH_UNICODE flag solved the problem
(utf-8 was sent to Oracle), but another warning was issued:
* SAWarning: cx_Oracle is compiled under Python 2.xx using the
WITH_UNICODE flag.  Consider recompiling cx_Oracle without this flag,
which is in no way necessary for full support of Unicode. Otherwise,
all string-holding bind parameters must be explicitly typed using
SQLAlchemy's String type or one of its subtypes,or otherwise be passed
as Python unicode.  Plain Python strings passed as bind parameters
will be silently corrupted by cx_Oracle. *

Right now I am using cx_Oracle compiled with WITH_UNICODE, everything
works, but this warning is worrying me. I tried to pass a str() object
in UTF-8 to SqlAlchemy, and the execution halted with an encoding
error (UnicodeDecodeError). In other words, cx_Oracle did not silently
corrupted the data (at least when special characters were sent).

I would like to know if anyone has a better (safer) solution to my
problem. Or am I safe enough by using the WITH_UNICODE flag and
passing only unicode() objects?

Thank you in advance.

Guilherme.

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



Re: [sqlalchemy] declarative one to many relationship with composite primary key

2010-11-17 Thread Michael Bayer

On Nov 17, 2010, at 9:07 AM, Adrien Saladin wrote:

 On Wed, Nov 17, 2010 at 1:16 AM, Michael Bayer mike...@zzzcomputing.com 
 wrote:
 ForeignKeyConstraint needs to go into __table_args__ when using declarative.
 
 http://www.sqlalchemy.org/docs/orm/extensions/declarative.html#table-configuration
 
 Thanks for the note. I have updated my test script to use
 __table_args__  but the error remains the same (see script and ouput
 below).

OK its actually a huge SQLA bug that an error isn't raised for that, which is 
surprising to me, so I created and resolved #1972 in r67d8f4e2fcb9.   
__table_args__ is expected to be a tuple or dict, so now an error is raised if 
it's not.   (x) isn't a tuple.   

here's the correct form:

class Bar(Base):
  __tablename__ = bar
  __table_args__ = (  ForeignKeyConstraint(['one_id', 'two_id'], ['foo.one', 
'foo.two']),{} )
  id = Column(Integer, primary_key=True)
  one_id = Column(Integer, nullable=False)
  two_id = Column(Integer, nullable=False)

  foo = relationship(Foo, backref = bars)



 
 I then tried with the hybrid approach
 (http://www.sqlalchemy.org/docs/orm/extensions/declarative.html#using-a-hybrid-approach-with-table)
 which works well.
 Am I again doing something wrong with declarative ?
 
 Thanks,
 
 
 #
 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative  import declarative_base
 
 
 Base = declarative_base()
 
 class Foo(Base):
   __tablename__ = foo
   one = Column(Integer, primary_key=True)
   two = Column(Integer, primary_key=True)
 
 class Bar(Base):
   __tablename__ = bar
   __table_args__ = (  ForeignKeyConstraint(['one_id', 'two_id'],
 ['foo.one', 'foo.two']) )
   id = Column(Integer, primary_key=True)
   one_id = Column(Integer, nullable=False)
   two_id = Column(Integer, nullable=False)
 
   foo = relationship(Foo, backref = bars)
 
 
 
 metadata = Base.metadata
 
 engine = create_engine('sqlite:///:memory:', echo=True)
 metadata.create_all(engine)
 
 from sqlalchemy.orm import sessionmaker
 
 # create a configured Session class
 Session = sessionmaker(bind=engine)
 
 # create a Session
 session = Session()
 
 foo = Foo()
 foo.one = 1
 foo.two = 2
 session.add(foo)
 session.commit()
 
 #
 
 
 
 2010-11-17 14:56:01,309 INFO sqlalchemy.engine.base.Engine.0x...9690
 PRAGMA table_info(foo)
 2010-11-17 14:56:01,309 INFO sqlalchemy.engine.base.Engine.0x...9690 ()
 2010-11-17 14:56:01,310 INFO sqlalchemy.engine.base.Engine.0x...9690
 PRAGMA table_info(bar)
 2010-11-17 14:56:01,310 INFO sqlalchemy.engine.base.Engine.0x...9690 ()
 2010-11-17 14:56:01,310 INFO sqlalchemy.engine.base.Engine.0x...9690
 CREATE TABLE foo (
one INTEGER NOT NULL,
two INTEGER NOT NULL,
PRIMARY KEY (one, two)
 )
 
 
 2010-11-17 14:56:01,310 INFO sqlalchemy.engine.base.Engine.0x...9690 ()
 2010-11-17 14:56:01,310 INFO sqlalchemy.engine.base.Engine.0x...9690 COMMIT
 2010-11-17 14:56:01,311 INFO sqlalchemy.engine.base.Engine.0x...9690
 CREATE TABLE bar (
id INTEGER NOT NULL,
one_id INTEGER NOT NULL,
two_id INTEGER NOT NULL,
PRIMARY KEY (id)
 )
 
 
 2010-11-17 14:56:01,311 INFO sqlalchemy.engine.base.Engine.0x...9690 ()
 2010-11-17 14:56:01,311 INFO sqlalchemy.engine.base.Engine.0x...9690 COMMIT
 Traceback (most recent call last):
  File compositePrimaryKey_decl.py, line 39, in module
foo = Foo()
  File string, line 4, in __init__
  File 
 /home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/state.py,
 line 93, in initialize_instance
fn(self, instance, args, kwargs)
  File 
 /home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/mapper.py,
 line 2357, in _event_on_init
instrumenting_mapper.compile()
  File 
 /home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/mapper.py,
 line 805, in compile
mapper._post_configure_properties()
  File 
 /home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/mapper.py,
 line 834, in _post_configure_properties
prop.init()
  File 
 /home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/interfaces.py,
 line 493, in init
self.do_init()
  File 
 /home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/properties.py,
 line 840, in do_init
self._determine_joins()
  File 
 /home/virtualenvs/sqlalchemy/lib/python2.6/site-packages/sqlalchemy/orm/properties.py,
 line 969, in _determine_joins
% self)
 sqlalchemy.exc.ArgumentError: Could not determine join condition
 between parent/child tables on relationship Bar.foo.  Specify a
 'primaryjoin' expression.  If this is a many-to-many relationship,
 'secondaryjoin' is needed as well.
 
 
 The script below works with the hybrid declarative approach:
 
 #
 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative  import declarative_base
 
 
 Base = declarative_base()
 
 class 

Re: [sqlalchemy] is there a way to add methods to sqlsoup's MappedFoo classes?

2010-11-17 Thread Michael Bayer

On Nov 17, 2010, at 4:23 AM, J wrote:

 so i'm using sqlsoup to support a legacy db, and am thoroughly
 enjoying it.  it was awesome setting up relationships and all that
 even though the underlying db schema didn't have any foreign key
 defines!
 
 however, i'm at a point where i'd like to add some helper funcitons/
 methods to some MappedFoo objects that sqlsoup likes to return.
 
 i was thinking of using a mixin to add the extra functionality.  for
 example:
 
 # assume foo is a MappedFoo instance returned from sqlsoup already
 class x:
   def bar(): print 'bar'
 foo.__bases__ += (x,)
 foo.bar() # prints 'bar' as expected
 
 however, it would be super if there was some way to have the sqlsoup
 getters already have this mixin or some overriding baseclass
 configured... or some automated way of applying a mixin behind the
 scenes.

SqlSoup allows a base argument which will serve as the base class for all 
generated classes:

SqlSoup(engine, base=MyClass)

we should probably add the constructor and stuff to the docstrings.



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

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



Re: [sqlalchemy] Encoding issue with SqlAlchemy + cxOracle

2010-11-17 Thread Michael Bayer

On Nov 17, 2010, at 10:26 AM, Guilherme Menezes wrote:

 Hi,
 
 I am having an encoding issue using Python 2.6.2, SqlAlchemy 0.6.5 and
 cxOracle 5.0.4 to access an Oracle 11g database.
 
 I am using the NLS_LANG=.AL32UTF8 enviroment variable. My table in
 Oracle is correctly configured to accept Unicode.
 
 First, I compiled cxOracle without the WITH_UNICODE flag (as
 recommended by SqlAlchemy).  I was passing data to SqlAlchemy as
 unicode() objects. Everything worked without errors or warnings.
 
 However, sometimes Oracle would complain that the string I was trying
 to insert into a VARCHAR2 field was too big ( 4000), even when the
 string size ( len(the_string.encode('utf-8')) ) was about 2300 bytes
 (before SqlAlchemy). I used a sniffer to verify that the Oracle client
 was sending two bytes for each character (even the ASCII ones),
 instead of sending two bytes only for special characters.
 
 I repeated this insertion experiment using cx_Oracle directly and
 passing unicode() objects to it. Same thing: no errors or warnings,
 and again the sniffer shown that the Oracle client was sending two
 bytes per character. It seemed to me that cx_Oracle does not really
 supports unicode() objects; it accepts them but it does not encode()
 them to the correct encoding (as set in NLS_LANG variable).
 
 However, when reading data from Oracle everything worked as expected
 (i.e. someone was converting the UTF-16(?) string to UTF-8, probably
 Oracle itself).
 
 I tried two approaches to make the Oracle client send data in UTF-8
 (not UTF-16):
 
 1. Passing str() objects to SqlAlchemy. SqlAlchemy would then complain
 in a warning:
 * UnicodeWarning: Unicode equal comparison failed to convert both
 arguments to Unicode - interpreting them as being unequal *
 It worked, but it did not seem right, since I was receiving unicode()
 objects and sending str() objetcs to SqlAlchemy. Moreover, I did not
 know how things work inside SqlAlchemy, so I tried something else.
 
 2. Compiling cx_Oracle with the WITH_UNICODE flag solved the problem
 (utf-8 was sent to Oracle), but another warning was issued:
 * SAWarning: cx_Oracle is compiled under Python 2.xx using the
 WITH_UNICODE flag.  Consider recompiling cx_Oracle without this flag,
 which is in no way necessary for full support of Unicode. Otherwise,
 all string-holding bind parameters must be explicitly typed using
 SQLAlchemy's String type or one of its subtypes,or otherwise be passed
 as Python unicode.  Plain Python strings passed as bind parameters
 will be silently corrupted by cx_Oracle. *
 
 Right now I am using cx_Oracle compiled with WITH_UNICODE, everything
 works, but this warning is worrying me. I tried to pass a str() object
 in UTF-8 to SqlAlchemy, and the execution halted with an encoding
 error (UnicodeDecodeError). In other words, cx_Oracle did not silently
 corrupted the data (at least when special characters were sent).
 
 I would like to know if anyone has a better (safer) solution to my
 problem. Or am I safe enough by using the WITH_UNICODE flag and
 passing only unicode() objects?


Regarding the passing of utf-8 vs. utf-16 and the differences in WITH_UNICODE 
mode, you should really email the cx_oracle list about that as WITH_UNICODE to 
my knowledge only has to do with the Python interpretation of arguments, not 
its interaction with OCI.   If you email their list, make sure all code 
examples are purely derived from cx_oracle, to eliminate any doubt that each 
behavior is one of cx_oracle directly.  WITH_UNICODE was not intended for 
general use in Python 2.xx.   if your whole application really works with it, 
then there's no reason not to use it, its just that you'll always have to 
ensure that no non-Python unicode strings ever get sent to cx_oracle which can 
be fairly tedious.   It sounds like a bug that cx_oracle would be expanding 
into a two-byte-per-character stream like that.

Its possible that calling setinputsizes() with cx_oracle.UNICODE may be the key 
to cx_oracle's behavior here.   We call setinputsizes for every Oracle cursor 
but we currently exclude the string types from that list as it had some 
unwanted side effects.

Also note that VARCHAR2(4000) is measuring itself in bytes, not characters.  
For true Unicode support Oracle provides the NVARCHAR2 type, where the length 
specifies the number of characters, instead of bytes.   Recent versions of 
Oracle also support the form VARCHAR2(4000 CHAR) which will similarly measure 
the column in terms of characters based on the databases encoding instead of 
bytes.Its worth investigating if using NVARCHAR2 causes cx_oracle, or OCI, 
to change its behavior.


 
 Thank you in advance.
 
 Guilherme.
 
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To post to this group, send email to sqlalch...@googlegroups.com.
 To unsubscribe from this group, send email to 
 sqlalchemy+unsubscr...@googlegroups.com.
 For more options, visit 

Re: [sqlalchemy] Encoding issue with SqlAlchemy + cxOracle

2010-11-17 Thread Guilherme Menezes
Thank you.

I will report the problem to the cx_Oracle list and see what they have to say.

Regards,

Guilherme.


On Wed, Nov 17, 2010 at 2:16 PM, Michael Bayer mike...@zzzcomputing.com wrote:

 On Nov 17, 2010, at 10:26 AM, Guilherme Menezes wrote:

 Hi,

 I am having an encoding issue using Python 2.6.2, SqlAlchemy 0.6.5 and
 cxOracle 5.0.4 to access an Oracle 11g database.

 I am using the NLS_LANG=.AL32UTF8 enviroment variable. My table in
 Oracle is correctly configured to accept Unicode.

 First, I compiled cxOracle without the WITH_UNICODE flag (as
 recommended by SqlAlchemy).  I was passing data to SqlAlchemy as
 unicode() objects. Everything worked without errors or warnings.

 However, sometimes Oracle would complain that the string I was trying
 to insert into a VARCHAR2 field was too big ( 4000), even when the
 string size ( len(the_string.encode('utf-8')) ) was about 2300 bytes
 (before SqlAlchemy). I used a sniffer to verify that the Oracle client
 was sending two bytes for each character (even the ASCII ones),
 instead of sending two bytes only for special characters.

 I repeated this insertion experiment using cx_Oracle directly and
 passing unicode() objects to it. Same thing: no errors or warnings,
 and again the sniffer shown that the Oracle client was sending two
 bytes per character. It seemed to me that cx_Oracle does not really
 supports unicode() objects; it accepts them but it does not encode()
 them to the correct encoding (as set in NLS_LANG variable).

 However, when reading data from Oracle everything worked as expected
 (i.e. someone was converting the UTF-16(?) string to UTF-8, probably
 Oracle itself).

 I tried two approaches to make the Oracle client send data in UTF-8
 (not UTF-16):

 1. Passing str() objects to SqlAlchemy. SqlAlchemy would then complain
 in a warning:
 * UnicodeWarning: Unicode equal comparison failed to convert both
 arguments to Unicode - interpreting them as being unequal *
 It worked, but it did not seem right, since I was receiving unicode()
 objects and sending str() objetcs to SqlAlchemy. Moreover, I did not
 know how things work inside SqlAlchemy, so I tried something else.

 2. Compiling cx_Oracle with the WITH_UNICODE flag solved the problem
 (utf-8 was sent to Oracle), but another warning was issued:
 * SAWarning: cx_Oracle is compiled under Python 2.xx using the
 WITH_UNICODE flag.  Consider recompiling cx_Oracle without this flag,
 which is in no way necessary for full support of Unicode. Otherwise,
 all string-holding bind parameters must be explicitly typed using
 SQLAlchemy's String type or one of its subtypes,or otherwise be passed
 as Python unicode.  Plain Python strings passed as bind parameters
 will be silently corrupted by cx_Oracle. *

 Right now I am using cx_Oracle compiled with WITH_UNICODE, everything
 works, but this warning is worrying me. I tried to pass a str() object
 in UTF-8 to SqlAlchemy, and the execution halted with an encoding
 error (UnicodeDecodeError). In other words, cx_Oracle did not silently
 corrupted the data (at least when special characters were sent).

 I would like to know if anyone has a better (safer) solution to my
 problem. Or am I safe enough by using the WITH_UNICODE flag and
 passing only unicode() objects?


 Regarding the passing of utf-8 vs. utf-16 and the differences in WITH_UNICODE 
 mode, you should really email the cx_oracle list about that as WITH_UNICODE 
 to my knowledge only has to do with the Python interpretation of arguments, 
 not its interaction with OCI.   If you email their list, make sure all code 
 examples are purely derived from cx_oracle, to eliminate any doubt that each 
 behavior is one of cx_oracle directly.  WITH_UNICODE was not intended for 
 general use in Python 2.xx.   if your whole application really works with it, 
 then there's no reason not to use it, its just that you'll always have to 
 ensure that no non-Python unicode strings ever get sent to cx_oracle which 
 can be fairly tedious.   It sounds like a bug that cx_oracle would be 
 expanding into a two-byte-per-character stream like that.

 Its possible that calling setinputsizes() with cx_oracle.UNICODE may be the 
 key to cx_oracle's behavior here.   We call setinputsizes for every Oracle 
 cursor but we currently exclude the string types from that list as it had 
 some unwanted side effects.

 Also note that VARCHAR2(4000) is measuring itself in bytes, not characters.  
 For true Unicode support Oracle provides the NVARCHAR2 type, where the 
 length specifies the number of characters, instead of bytes.   Recent 
 versions of Oracle also support the form VARCHAR2(4000 CHAR) which will 
 similarly measure the column in terms of characters based on the databases 
 encoding instead of bytes.    Its worth investigating if using NVARCHAR2 
 causes cx_oracle, or OCI, to change its behavior.



 Thank you in advance.

 Guilherme.

 --
 You received this message because you are subscribed to the Google Groups 
 

[sqlalchemy] Removing an element from an uncascaded many-to-many

2010-11-17 Thread Joril
Hi everyone!

I'm puzzled by a behaviour shown by SA 0.6.5 that 0.5.8 didn't show,
and I'm wondering what I'm doing wrong.. I have a simple uncascaded
many-to-many relationship, and if I try the following:

1) save a child
2) close the session
3) associate the child to a parent and save the parent
4) deassociate the child and save the parent

the association doesn't get removed from the junction table.. If I
skip closing the session, it DOES get removed...
Here's an example:


from sqlalchemy import Column, String, Integer, Table, ForeignKey
from sqlalchemy.engine import create_engine
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

junction = Table(junction, Base.metadata, Column(p_id,
ForeignKey(parents.id)),
Column(c_id,
ForeignKey(children.id)))

class Child(Base):
   __tablename__ = children

   id = Column(Integer, primary_key=True)

class Parent(Base):
   __tablename__ = parents

   id = Column(Integer, primary_key=True)
   children = relationship(Child, secondary=junction, cascade=)


def save(session, x):
   session.add(x)
   session.flush()

en = create_engine(sqlite:///:memory:, echo=True)
Base.metadata.create_all(en)
maker = sessionmaker(en)
session = maker(autocommit=True)

# Save a child and close the session
c = Child()
save(session, c)
session.close()

# Associate the child to a parent and save
p = Parent()
p.children = [c]
save(session, p)

# Try to remove the child
p.children = []
save(session, p)


I'd expect that the last command would log something like

BEGIN (implicit)
SELECT children.id AS children_id
FROM children
WHERE children.id = ?
(1,)
DELETE FROM junction WHERE junction.p_id = ? AND junction.c_id = ?
(1, 1)
COMMIT
SELECT parents.id AS parents_id
FROM parents
WHERE parents.id = ?
(1,)


but instead I get only


BEGIN (implicit)
COMMIT
SELECT parents.id AS parents_id
FROM parents
WHERE parents.id = ?
(1,)


This used to work with 0.5.8, what am I doing wrong?

Many thanks for your attention!

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



Re: [sqlalchemy] Problems when querying the database

2010-11-17 Thread Michael Bayer

On Nov 16, 2010, at 3:56 PM, Alvaro Reinoso wrote:

 Hi all,
 
 I have a problem when querying the database:
 
 This channel class:
 
 class Channel(rdb.Model):
   Represents both complex channels and trivial ones (media)
   rdb.metadata(metadata)
   rdb.tablename(channels)
 
   id = Column(id, Integer, primary_key=True)
   title = Column(title, String(100))

 
   items = relationship(MediaItem, secondary=channel_items,
 order_by=MediaItem.position, backref=channels)
 
 I get the proper channel object if I do:
 
   channel = session.query(Channel).filter(Channel.title == title)

filter() always returns a Query object, not an instance.   So there is no 
difference here between the call above and the one on MediaGroup, as far as the 
return result being a Query.





 
 And this is my mediaGroup class:
 
 class MediaGroup(rdb.Model):
   Represents MediaGroup class. Contains channels and other media
 groups
   rdb.metadata(metadata)
   rdb.tablename(media_groups)
 
   id = Column(id, Integer, primary_key=True)
   title = Column(title, String(100))
   
 
   channels = relationship(Channel, secondary=media_group_channels,
 order_by=Channel.titleView, backref=media_groups)
   mediaGroups = relationship(MediaGroup,
 secondary=media_group_groups, order_by=MediaGroup.title,
   primaryjoin=lambda: MediaGroup.id ==
 media_group_groups.c.media_groupA_id,
   secondaryjoin=lambda: MediaGroup.id ==
 media_group_groups.c.media_groupB_id,
   backref=media_groups)
 
 I get the Query object object if I do:
 
   mediaGroup = session.query(MediaGroup).filter(MediaGroup.title ==
 title)
 
 I don't know if it's because of the relationships but I tried without
 mediaGroups relation, and I didn't work either.
 
 Any idea??
 
 Thanks!
 
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To post to this group, send email to sqlalch...@googlegroups.com.
 To unsubscribe from this group, send email to 
 sqlalchemy+unsubscr...@googlegroups.com.
 For more options, visit this group at 
 http://groups.google.com/group/sqlalchemy?hl=en.
 

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



Re: [sqlalchemy] declarative one to many relationship with composite primary key

2010-11-17 Thread Adrien Saladin
On Wed, Nov 17, 2010 at 4:58 PM, Michael Bayer mike...@zzzcomputing.com wrote:
 OK its actually a huge SQLA bug that an error isn't raised for that, which is 
 surprising to me, so I created and resolved #1972 in r67d8f4e2fcb9.   
 __table_args__ is expected to be a tuple or dict, so now an error is raised 
 if it's not.   (x) isn't a tuple.


Thanks for the quick reply, the patch and the syntax correction of my code.

Regards,

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



Re: [sqlalchemy] Removing an element from an uncascaded many-to-many

2010-11-17 Thread Michael Bayer
you've turned off save-update cascade so the c object is not placed into 
the Session when you do the final save() of p.

Fix:

session.add_all(p.children)
p.children = []

save(session, p)


On Nov 17, 2010, at 12:38 PM, Joril wrote:

 from sqlalchemy import Column, String, Integer, Table, ForeignKey
 from sqlalchemy.engine import create_engine
 from sqlalchemy.orm import sessionmaker, relationship
 from sqlalchemy.ext.declarative import declarative_base
 
 Base = declarative_base()
 
 junction = Table(junction, Base.metadata, Column(p_id,
 ForeignKey(parents.id)),
Column(c_id,
 ForeignKey(children.id)))
 
 class Child(Base):
   __tablename__ = children
 
   id = Column(Integer, primary_key=True)
 
 class Parent(Base):
   __tablename__ = parents
 
   id = Column(Integer, primary_key=True)
   children = relationship(Child, secondary=junction, cascade=)
 
 
 def save(session, x):
   session.add(x)
   session.flush()
 
 en = create_engine(sqlite:///:memory:, echo=True)
 Base.metadata.create_all(en)
 maker = sessionmaker(en)
 session = maker(autocommit=True)
 
 # Save a child and close the session
 c = Child()
 save(session, c)
 session.close()
 
 # Associate the child to a parent and save
 p = Parent()
 p.children = [c]
 save(session, p)
 
 # Try to remove the child
 p.children = []
 save(session, p)
 

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



Re: [sqlalchemy] Removing an element from an uncascaded many-to-many

2010-11-17 Thread Michael Bayer
I'll also make the comment that while the pattern you're illustrating is very 
unusual (cascade turned off, re-adding detached objects), the ORM is not being 
consistent in its treatment of non-included child items in mutated 
collections during flush, in that your append got flushed but the delete 
doesn't - there's specific code to that effect, which is also not consistent 
against one-to-many.  I've added ticket 1973 which, if it proceeds, would 
likely be in 0.7.


On Nov 17, 2010, at 2:57 PM, Michael Bayer wrote:

 you've turned off save-update cascade so the c object is not placed into 
 the Session when you do the final save() of p.
 
 Fix:
 
 session.add_all(p.children)
 p.children = []
 
 save(session, p)
 
 
 On Nov 17, 2010, at 12:38 PM, Joril wrote:
 
 from sqlalchemy import Column, String, Integer, Table, ForeignKey
 from sqlalchemy.engine import create_engine
 from sqlalchemy.orm import sessionmaker, relationship
 from sqlalchemy.ext.declarative import declarative_base
 
 Base = declarative_base()
 
 junction = Table(junction, Base.metadata, Column(p_id,
 ForeignKey(parents.id)),
Column(c_id,
 ForeignKey(children.id)))
 
 class Child(Base):
   __tablename__ = children
 
   id = Column(Integer, primary_key=True)
 
 class Parent(Base):
   __tablename__ = parents
 
   id = Column(Integer, primary_key=True)
   children = relationship(Child, secondary=junction, cascade=)
 
 
 def save(session, x):
   session.add(x)
   session.flush()
 
 en = create_engine(sqlite:///:memory:, echo=True)
 Base.metadata.create_all(en)
 maker = sessionmaker(en)
 session = maker(autocommit=True)
 
 # Save a child and close the session
 c = Child()
 save(session, c)
 session.close()
 
 # Associate the child to a parent and save
 p = Parent()
 p.children = [c]
 save(session, p)
 
 # Try to remove the child
 p.children = []
 save(session, p)
 
 
 
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To post to this group, send email to sqlalch...@googlegroups.com.
 To unsubscribe from this group, send email to 
 sqlalchemy+unsubscr...@googlegroups.com.
 For more options, visit this group at 
 http://groups.google.com/group/sqlalchemy?hl=en.

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



[sqlalchemy] Re: is there a way to add methods to sqlsoup's MappedFoo classes?

2010-11-17 Thread J
hmm... but i was thinking of having specialized methods for every
table/object.  am i missing something from your suggestion?  how would
you have a base class that would somehow specialize depending on the
child object?

i went ahead and executed my mixin idea by attacking the db._cache
dict with the mixins:

def __bind_mixins(db):
   for table_name,v in db._cache.items():
  # this is pretty retarded, just truncates last letter assuming
's' plural
  mixin_name = table_name[:-1]
  try:
 # this is also pretty retarded.  __import__() didn't quite
work.
 # i'm thinking it was a circular import/runtime execution
order issue
 exec 'from mixins.%s import %s' % (mixin_name, mixin_name)
 mixin_cls = locals()[mixin_name]
db._cache[table_name].__bases__ += (mixin_cls,)
  except ImportError: pass


On Nov 17, 8:02 am, Michael Bayer mike...@zzzcomputing.com wrote:
 On Nov 17, 2010, at 4:23 AM, J wrote:



  so i'm using sqlsoup to support a legacy db, and am thoroughly
  enjoying it.  it was awesome setting up relationships and all that
  even though the underlying db schema didn't have any foreign key
  defines!

  however, i'm at a point where i'd like to add some helper funcitons/
  methods to some MappedFoo objects that sqlsoup likes to return.

  i was thinking of using a mixin to add the extra functionality.  for
  example:

  # assume foo is a MappedFoo instance returned from sqlsoup already
  class x:
    def bar(): print 'bar'
  foo.__bases__ += (x,)
  foo.bar() # prints 'bar' as expected

  however, it would be super if there was some way to have the sqlsoup
  getters already have this mixin or some overriding baseclass
  configured... or some automated way of applying a mixin behind the
  scenes.

 SqlSoup allows a base argument which will serve as the base class for all 
 generated classes:

         SqlSoup(engine, base=MyClass)

 we should probably add the constructor and stuff to the docstrings.



  thoughs?  thanks.

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



Re: [sqlalchemy] Re: is there a way to add methods to sqlsoup's MappedFoo classes?

2010-11-17 Thread Michael Bayer

On Nov 17, 2010, at 4:05 PM, J wrote:

 hmm... but i was thinking of having specialized methods for every
 table/object.  am i missing something from your suggestion?  

No, SqlSoup only offers the base class for all objects as an option.  Here's a 
patch you can try:

diff -r 67d8f4e2fcb9 lib/sqlalchemy/ext/sqlsoup.py
--- a/lib/sqlalchemy/ext/sqlsoup.py Wed Nov 17 10:55:10 2010 -0500
+++ b/lib/sqlalchemy/ext/sqlsoup.py Wed Nov 17 16:17:23 2010 -0500
@@ -540,7 +540,7 @@
 j = join(*args, **kwargs)
 return self.map(j)
 
-def entity(self, attr, schema=None):
+def entity(self, attr, schema=None, base=None):
 try:
 t = self._cache[attr]
 except KeyError, ke:
@@ -548,7 +548,7 @@
 if not table.primary_key.columns:
 raise PKNotFoundError('table %r does not have a primary key 
defined [columns: %s]' % (attr, ','.join(table.c.keys(
 if table.columns:
-t = _class_for_table(self.session, self.engine, table, 
self.base)
+t = _class_for_table(self.session, self.engine, table, base or 
self.base)
 else:
 t = None
 self._cache[attr] = t


mysoup.entity('mytable', base=MyBaseClass)



 how would
 you have a base class that would somehow specialize depending on the
 child object?
 
 i went ahead and executed my mixin idea by attacking the db._cache
 dict with the mixins:
 
 def __bind_mixins(db):
   for table_name,v in db._cache.items():
  # this is pretty retarded, just truncates last letter assuming
 's' plural
  mixin_name = table_name[:-1]
  try:
 # this is also pretty retarded.  __import__() didn't quite
 work.
 # i'm thinking it was a circular import/runtime execution
 order issue
 exec 'from mixins.%s import %s' % (mixin_name, mixin_name)
 mixin_cls = locals()[mixin_name]
 db._cache[table_name].__bases__ += (mixin_cls,)
  except ImportError: pass
 
 
 On Nov 17, 8:02 am, Michael Bayer mike...@zzzcomputing.com wrote:
 On Nov 17, 2010, at 4:23 AM, J wrote:
 
 
 
 so i'm using sqlsoup to support a legacy db, and am thoroughly
 enjoying it.  it was awesome setting up relationships and all that
 even though the underlying db schema didn't have any foreign key
 defines!
 
 however, i'm at a point where i'd like to add some helper funcitons/
 methods to some MappedFoo objects that sqlsoup likes to return.
 
 i was thinking of using a mixin to add the extra functionality.  for
 example:
 
 # assume foo is a MappedFoo instance returned from sqlsoup already
 class x:
   def bar(): print 'bar'
 foo.__bases__ += (x,)
 foo.bar() # prints 'bar' as expected
 
 however, it would be super if there was some way to have the sqlsoup
 getters already have this mixin or some overriding baseclass
 configured... or some automated way of applying a mixin behind the
 scenes.
 
 SqlSoup allows a base argument which will serve as the base class for all 
 generated classes:
 
 SqlSoup(engine, base=MyClass)
 
 we should probably add the constructor and stuff to the docstrings.
 
 
 
 thoughs?  thanks.
 
 --
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To post to this group, send email to sqlalch...@googlegroups.com.
 To unsubscribe from this group, send email to 
 sqlalchemy+unsubscr...@googlegroups.com.
 For more options, visit this group 
 athttp://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 sqlalch...@googlegroups.com.
 To unsubscribe from this group, send email to 
 sqlalchemy+unsubscr...@googlegroups.com.
 For more options, visit this group at 
 http://groups.google.com/group/sqlalchemy?hl=en.
 

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



[sqlalchemy] Re: is there a way to add methods to sqlsoup's MappedFoo classes?

2010-11-17 Thread J
to get this working, i had to add a line to clear the cache entry for
attr if the base argument was passed in:

def entity(self, attr, schema=None, base=None):
if base: del self._cache[attr]   # ADDED LINE
try:
t = self._cache[attr]
except KeyError, ke:
table = Table(attr, self._metadata, autoload=True,
autoload_with=self.bind, schema=schema or self.schema)
if not table.primary_key.columns:
raise PKNotFoundError('table %r does not have a
primary key defined [columns: %s]' % (attr, ','.join(table.c.keys(
if table.columns:
t = _class_for_table(self.session, self.engine, table,
base or self.base)
else:
t = None
self._cache[attr] = t
return t

it works now no matter when it's called.  pretty neat.

On Nov 17, 1:19 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 On Nov 17, 2010, at 4:05 PM, J wrote:

  hmm... but i was thinking of having specialized methods for every
  table/object.  am i missing something from your suggestion?  

 No, SqlSoup only offers the base class for all objects as an option.  Here's 
 a patch you can try:

 diff -r 67d8f4e2fcb9 lib/sqlalchemy/ext/sqlsoup.py
 --- a/lib/sqlalchemy/ext/sqlsoup.py     Wed Nov 17 10:55:10 2010 -0500
 +++ b/lib/sqlalchemy/ext/sqlsoup.py     Wed Nov 17 16:17:23 2010 -0500
 @@ -540,7 +540,7 @@
          j = join(*args, **kwargs)
          return self.map(j)

 -    def entity(self, attr, schema=None):
 +    def entity(self, attr, schema=None, base=None):
          try:
              t = self._cache[attr]
          except KeyError, ke:
 @@ -548,7 +548,7 @@
              if not table.primary_key.columns:
                  raise PKNotFoundError('table %r does not have a primary key 
 defined [columns: %s]' % (attr, ','.join(table.c.keys(
              if table.columns:
 -                t = _class_for_table(self.session, self.engine, table, 
 self.base)
 +                t = _class_for_table(self.session, self.engine, table, base 
 or self.base)
              else:
                  t = None
              self._cache[attr] = t

 mysoup.entity('mytable', base=MyBaseClass)

  how would
  you have a base class that would somehow specialize depending on the
  child object?

  i went ahead and executed my mixin idea by attacking the db._cache
  dict with the mixins:

  def __bind_mixins(db):
    for table_name,v in db._cache.items():
       # this is pretty retarded, just truncates last letter assuming
  's' plural
       mixin_name = table_name[:-1]
       try:
          # this is also pretty retarded.  __import__() didn't quite
  work.
          # i'm thinking it was a circular import/runtime execution
  order issue
          exec 'from mixins.%s import %s' % (mixin_name, mixin_name)
          mixin_cls = locals()[mixin_name]
  db._cache[table_name].__bases__ += (mixin_cls,)
       except ImportError: pass

  On Nov 17, 8:02 am, Michael Bayer mike...@zzzcomputing.com wrote:
  On Nov 17, 2010, at 4:23 AM, J wrote:

  so i'm using sqlsoup to support a legacy db, and am thoroughly
  enjoying it.  it was awesome setting up relationships and all that
  even though the underlying db schema didn't have any foreign key
  defines!

  however, i'm at a point where i'd like to add some helper funcitons/
  methods to some MappedFoo objects that sqlsoup likes to return.

  i was thinking of using a mixin to add the extra functionality.  for
  example:

  # assume foo is a MappedFoo instance returned from sqlsoup already
  class x:
    def bar(): print 'bar'
  foo.__bases__ += (x,)
  foo.bar() # prints 'bar' as expected

  however, it would be super if there was some way to have the sqlsoup
  getters already have this mixin or some overriding baseclass
  configured... or some automated way of applying a mixin behind the
  scenes.

  SqlSoup allows a base argument which will serve as the base class for 
  all generated classes:

          SqlSoup(engine, base=MyClass)

  we should probably add the constructor and stuff to the docstrings.

  thoughs?  thanks.

  --
  You received this message because you are subscribed to the Google Groups 
  sqlalchemy group.
  To post to this group, send email to sqlalch...@googlegroups.com.
  To unsubscribe from this group, send email to 
  sqlalchemy+unsubscr...@googlegroups.com.
  For more options, visit this group 
  athttp://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 sqlalch...@googlegroups.com.
  To unsubscribe from this group, send email to 
  sqlalchemy+unsubscr...@googlegroups.com.
  For more options, visit this group 
  athttp://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 sqlalch...@googlegroups.com.
To