[sqlalchemy] Mapping a graph data structure

2006-11-01 Thread Arnar Birgisson
Hi there,There was a question on IRC yesterday on how to map a graph (as in nodes and edges) with SA. I didn't have much time to dwell on this but this was a start: http://paste.ufsoft.org/90
I was curious if someone has done this successfully? The problem I have with the above is that the viewonly property _lower_neighbours isn't updated until the session is clear()ed and the object is reloaded. Is there a way to refresh a specific relation?
Now that I think about this, it would have been alot easier to create a directed graph and just create edges in both directions for an undirected one.Arnar

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


[sqlalchemy] Re: TurboEntity announcement

2006-11-01 Thread Gaetan de Menten

Hello,

Well, thank you for that. It's exactly what I needed.

The funny thing here is that I've been working on developping
approximately the same code for the past two or three weeks, with
exactly the same syntax... And I was about to announce it in a few
days (after cleaning it up and documenting it a bit)... I got a first
working prototype yesterday. I've looked briefly at your code and it
seems like we've taken drastically different approaches for exactly
the same goal.

Anyway, I'm too far in the process now to just let it go, so I'll just
finish it as if I didn't know your project existed, then I'll look at
what you did more thoroughly and either contribute to your project or
try to convince you to switch to mine. ;-)

PS: I hope I don't sound too frustrated here. Of course, I'm a bit
frustrated not to have been the first here, but I am sincerely happy
somebody did what I need.

Greetings,
Gaëtan.

On 10/30/06, Daniel Haus [EMAIL PROTECTED] wrote:

 TurboEntity is a high-level declarative layer on top of SQLAlchemy,
 inspired by - but somewhat thicker than - Jonathan LaCour's
 ActiveMapper extension.

 Features currently include:
 - automatic polymorphic inheritance
 - easy specification of relationships
 - automatic creation of primary keys
 - automatic creation of foreign keys
 - automatic creation of secondary tables
 - relations can be specified across modules

 More information, documentation, examples and baloons for the kids can
 be found at http://turboentity.ematia.de/

 And here's the blog post. Comments are open!
 http://www.danielhaus.de/2006/10/30/announcing-turboentity/

 Please let me know what you think about TurboEntity and if you find it
 useful.

 Greetings,
 Daniel


 


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



[sqlalchemy] Re: TurboEntity announcement

2006-11-01 Thread Daniel Haus

That's very good news, maybe we can pull together the
best pieces of both approaches? I'd really like to see
your solution.

Daniel


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



[sqlalchemy] Re: TurboEntity announcement

2006-11-01 Thread Gaetan de Menten

I'll send you a copy as soon as the basics work. For now, the system
is in place but only ManyToOne work. I wanted to also implement the 3
possible types of inheritance before publishing my code, but well, now
the circumstances are different... I'd be very glad if we could mix
both code bases.

FYI, the main difference in my code is that I don't defer classes, I
only defer fields, and create them as soon as what is needed for a
particular field is defined. So I had to implement a very simple
dependency system... It felt like a better approach but I'm not
really sure about it...

Gaëtan.

On 11/1/06, Daniel Haus [EMAIL PROTECTED] wrote:

 That's very good news, maybe we can pull together the
 best pieces of both approaches? I'd really like to see
 your solution.

 Daniel


 


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



[sqlalchemy] Re: Mapping a graph data structure

2006-11-01 Thread wyatt bC

Arnar Birgisson wrote:
 Hi there,

 There was a question on IRC yesterday on how to map a graph (as in nodes and
 edges) with SA. I didn't have much time to dwell on this but this was a
 start: http://paste.ufsoft.org/90

 I was curious if someone has done this successfully? The problem I have with
 the above is that the viewonly property _lower_neighbours isn't updated
 until the session is clear()ed and the object is reloaded. Is there a way to
 refresh a specific relation?

 Now that I think about this, it would have been a lot easier to create a
 directed graph and just create edges in both directions for an undirected
 one.

I haven't done this, but I'm curious about it as well. The application
I'm working on has a graph with ~100,000 edges. I have Node and Edge
tables/objects similar to yours but with some more fields. I pull stuff
from the DB to create an adjacency list, which I save to disk using the
marshal package (it gets saved as a .pyc file, ~7MB).

Reading the marshaled graph and running it through Dijkstra's shortest
paths algorithm is pretty fast. It takes about half a second to read in
the graph and another half second (on average) to get a result from
Dijkstra.

I'm using GIS data that is handed to me by someone else, and I don't
really have a need to invent a way to update it, since I could just use
GRASS or QGIS, but it's still an interesting problem.

Looking at your code, I'm curious about (confused by) the upper and
lower neighbors. Do you need to keep track of which neighbors are
above and below?

Here's a slightly modified version that doesn't use upper and lower and
only uses a single property, _neighbours. There is a flag for
add_neighbour that says whether the node being added (othernode) should
have the node being added to (self) as a neighbor. So, instead of this:

node1.add_neighbour(node2)
node2.add_neighbour(node1)

You'd do this:

node1.add_neighbour(node2, True)  # To say that node2 also connects
to node1

or:

node1.add_neighbour(node2, False)  # When node2 doesn't connect to
node1


#!/usr/bin/env python
import sys
import os
from sqlalchemy import *


engine = create_engine('sqlite://')
meta = BoundMetaData(engine)

nodes = Table('nodes', meta,
  Column(nodeid, Integer, primary_key=True)
)

edges = Table('edges', meta,
  Column(node_1_id, Integer, ForeignKey('nodes.nodeid')),
  Column(node_2_id, Integer, ForeignKey('nodes.nodeid'))
)


class Node(object):

def __str__(self):
return Node %d, neighbours [%s] % (self.nodeid,
','.join(map(str, [n.nodeid for n in self.neighbours])))

def get_neighbours(self):
return list(self._neighbours)

neighbours = property(get_neighbours)

def add_neighbour(self, othernode, both_ways=True):
if othernode not in self._neighbours:
self._neighbours.append(othernode)
if both_ways and self not in othernode._neighbours:
othernode._neighbours.append(self)


nodes_mapper = mapper(Node, nodes)
nodes2 = nodes.alias('nodes2')
nodes2_mapper = mapper(Node, nodes2, non_primary=True)
nodes_mapper.add_property('_neighbours',
relation(nodes2_mapper,
secondary=edges,
primaryjoin=nodes.c.nodeid==edges.c.node_1_id,
secondaryjoin=nodes2.c.nodeid==edges.c.node_2_id
)
)


def main():
meta.create_all()
s = create_session(engine)

for i in range(10):
n = Node()
n.nodeid = i
s.save(n)
s.flush()
s.clear()

nodes = s.query(Node).select()
nodes[1].add_neighbour(nodes[2])
nodes[1].add_neighbour(nodes[3])
nodes[1].add_neighbour(nodes[4])
nodes[4].add_neighbour(nodes[5], False)
nodes[5].add_neighbour(nodes[1], False)
nodes[2].add_neighbour(nodes[1])

for n in nodes:
print n


if __name__ == '__main__':
main()


Maybe that's useful? Maybe not. It was fun to think about it anyway.

__wyatt


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



[sqlalchemy] Re: Activemapper and selection

2006-11-01 Thread Jonathan LaCour

percious wrote:

 So, 2 questions.
 1) can we add a from clause to the active mapper?
 2) are there plans to alleviate the need for '.' replacement in the
 future?

Ooops, ignore part of my last reply, somehow my procmail filter dumped
your message into a different folder than my SQLAlchemy lists folder :)

Either way, my advice still applies.  It would be great if you could
illustrate with your example the current SQL that is being generated,
along with some improved SQL that would be faster.

--
Jonathan LaCour
http://cleverdevil.org

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



[sqlalchemy] Re: Activemapper and selection

2006-11-01 Thread Michael Bayer

if you use a table with mixed case identifiers, quotes are required.
additionally, SA's ORM queries use the use_label=True flag so that
joins among many tables can be constructed without the issue of column
names conflicting.

as for too much work on the MySQL side, i can assure you that you'd
hardly detect even a milliecond's difference in performance between
quoted/labeled and non, even if you ran the query a million times in
each style.  the database is *definitely* where you want to put the
most computation possible, compared to a Python script.


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



[sqlalchemy] Re: [Sqlalchemy-users] Typed Relations - Any Easier way to do Association Object?

2006-11-01 Thread Michael Bayer

(moving to google groups)

the idea of using an instrumented list subclass is that you *would*  
use the association object, and just have the list subclass handle  
the references to the association object for you, i.e.:

class MyList(list):
 def append(self, item):
 super(MyList, self).append(new ItemAssociation(item))
 def __getitem__(self, index):
 return super(MyList, self).__getitem__(index).item

..etc


On Nov 1, 2006, at 3:15 PM, Karl Guertin wrote:

 I'm working on a database where the relation between users and objects
 is defined by an association table that looks like:

 role_objects_table = Table(role_objects, metadata,
Column(objects_id, Integer,
   ForeignKey(objects.objects_id),
   primary_key=True),
Column(role,Role_Type),
Column(user_id, Integer,
   ForeignKey(tg_user.user_id),
   primary_key=True))

 Where Role_Type is an Enum class that translates roles onto Unicode 
 (1).

 And Objects is mapped like so:

 assign_mapper(session.context, Objects, objects_table, properties =  
 dict(
 #...
 responsibles = relation(User, secondary=role_objects_table,
 primaryjoin = and_(objects_table.c.objects_id ==
 role_objects_table.c.objects_id,
   role_objects_table.c.role == 'R')),
 approvers = relation(User, secondary=role_objects_table,
 primaryjoin = and_(objects_table.c.objects_id ==
 role_objects_table.c.objects_id,
   role_objects_table.c.role == 'A')),
#...
 )

 So basically the relationship between users and objects is typed by
 the role field. This is a textbook use case for the use of an
 association object, but using an association object is really
 annoying. I would really like to be able to treat each relation as a
 normal many to many relation and not have to create intermediate
 objects just to set one field to a constant value.

 In looking through the archives I found:

 You could go more nuts with [object properties] by having the list  
 be a
 subclass of list which properly does mutation operations too,  
 creates
 the association objects automatically, etc.

 Which seems to be what I'm looking to do. I'm assuming that the list
 referenced here is custom collection_class, but I don't see any
 obvious hooks into the secondary table and trying to manage the state
 of intermediate objects is more work than I'd like.

 In looking through the code, I noticed
 sqlalchemy.orm.attributes.AttributeExtension, which makes it pretty
 easy to hook into the event I'm interested in, but I'm having trouble
 finding a reference to the secondary table.

 Any guidance would be appreciated.

 -- 
 ---
 Using Tomcat but need to do more? Need to support web services,  
 security?
 Get stuff done quickly with pre-integrated technology to make your  
 job easier
 Download IBM WebSphere Application Server v.1.0.1 based on Apache  
 Geronimo
 http://sel.as-us.falkag.net/sel? 
 cmd=lnkkid=120709bid=263057dat=121642
 ___
 Sqlalchemy-users mailing list
 Sqlalchemy-users@lists.sourceforge.net
 https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users


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



[sqlalchemy] Re: [Sqlalchemy-users] Typed Relations - Any Easier way to do Association Object?

2006-11-01 Thread Karl Guertin

On 11/1/06, Michael Bayer [EMAIL PROTECTED] wrote:
 (moving to google groups)

Eh, sorry cached email address.

 the idea of using an instrumented list subclass is that you *would*
 use the association object, and just have the list subclass handle
 the references to the association object for you, i.e.:

Simple enough

 class MyList(list):
  def append(self, item):
  super(MyList, self).append(new ItemAssociation(item))
  def __getitem__(self, index):
  return super(MyList, self).__getitem__(index).item

 ..etc

I'm not understanding what's happening in the append. I know item is
one side of my relation, but how to I get access to the other? Is the
InstrumentedList magic supposed to handle this somehow?

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



[sqlalchemy] Re: [Sqlalchemy-users] Typed Relations - Any Easier way to do Association Object?

2006-11-01 Thread Michael Bayer
OK, i was oversimplifying.  if you really want a total bi-directional  
many-to-many relationship where the association object is essentially  
invisible, you have to set up proxies in both directions.  The  
attached script illustrates an almost generic way of doing this  
which, after a few more iterations, could possibly become an  
extension to SA so that folks could re-use this approach without the  
ugliness.  It basically sets up a proxy list that translates the  
association instances in both directions to the underlying target  
object.   in this example, both sides of the association are many-to- 
many.  further property tricks can be used to make one side of it  
scalar instead



--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sqlalchemy
-~--~~~~--~~--~--~---
from sqlalchemy import *
m = BoundMetaData('sqlite://', echo=True)

objecttable = Table('objects', m,
Column('id', Integer, primary_key=True),
Column('data', String(30))
)

associationtable = Table('association', m,
Column('oid', Integer, ForeignKey('objects.id'), primary_key=True),
Column('iid', Integer, ForeignKey('items.id'), primary_key=True))

itemtable = Table('items', m, 
Column('id', Integer, primary_key=True),
Column('data', String(30))
)

m.create_all()

class Association(object):
association object
pass

class AssociationList(object):
generic proxying list which proxies list operations to a different 
list-holding attribute of the parent object, converting Association objects
to and from a target attribute on each Association object.
def __init__(self, parent, collectionname, attr):
create a new AssociationList.

parent - the parent object that contains this list
collectionname - the attribute name which stores the collection of Associations
attr - name of the attribute on the Association in which to get/set target values

self.parent = parent
self.collectionname = collectionname
self.attr = attr
def append(self, item):
a = Association()
setattr(a, self.attr, item)
getattr(self.parent, self.collectionname).append(a)
def __iter__(self):
return iter([getattr(x, self.attr) for x in getattr(self.parent, self.collectionname)])
def __repr__(self):
return repr([getattr(x, self.attr) for x in getattr(self.parent, self.collectionname)])
def __len__(self):
return len(getattr(self.parent, self.collectionname))
def __getitem__(self, index):
return getattr(getattr(self.parent, self.collectionname)[index], self.attr)
def __setitem__(self, index, value):
a = Association()
setattr(a, self.attr, value)
getattr(self.parent, self.collectionname)[index] = a

class AssocProp(object):
a property object that automatically sets up AssociationLists on a parent object.
def __init__(self, collectionname, attr):
create a new association property.

collectionname - the attribute name which stores the collection of Associations
attr - name of the attribute on the Association in which to get/set target values

self.collectionname = collectionname
self.attr = attr
def __get__(self, obj, owner):
if obj is None:
return self
storage_key = '_AssocProp_%s' % self.collectionname
try:
return getattr(obj, storage_key)
except AttributeError:
a = AssociationList(obj, self.collectionname, self.attr)
setattr(obj, storage_key, a)
return a

class MyObject(object):
items = AssocProp('associations', 'item')

class Item(object):
myobjs = AssocProp('associations', 'myobj')

mapper(MyObject, objecttable)
mapper(Item, itemtable)

mapper(Association, associationtable, properties={
'myobj':relation(MyObject, backref='associations'),
'item':relation(Item, backref='associations')
})

s = create_session()

o = MyObject()
o.items.append(Item())
o.items.append(Item())

i = Item()
i.myobjs.append(o)

s.save(o)
s.flush()
s.clear()

o = s.query(MyObject).get(o.id)
print o
print o.items
assert len(o.items) == 3
assert o in o.items[1].myobjs



On Nov 1, 2006, at 7:09 PM, Karl Guertin wrote:


 On 11/1/06, Michael Bayer [EMAIL PROTECTED] wrote:
 (moving to google groups)

 Eh, sorry cached email address.

 the idea of using an instrumented list subclass is that you *would*
 use the association object, and just have the list subclass handle
 the references to the association object for you, i.e.:

 Simple enough

 class MyList(list):

[sqlalchemy] how to redefine a table object

2006-11-01 Thread robert rottermann
hi there,
I am new to SA.
For a tool I am creating I am also writing unittests.
In these I recreate the same table object repeatedly.
Up to now (with 0.28) this worked fine when I added
redefine=True.

In 0.3 this does not work anymore.
How would I remove/update a table from from a MetaData object?

How do I clean everything at the start of a unittest?

thanks
robert


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sqlalchemy
-~--~~~~--~~--~--~---
begin:vcard
fn:robert  rottermann
n:rottermann;robert 
email;internet:[EMAIL PROTECTED]
tel;work:031 333 10 20
tel;fax:031 333 10 23
tel;home:031 333 36 03
x-mozilla-html:FALSE
version:2.1
end:vcard