[sqlalchemy] Re: keyword-only arguments in entity constructor confuse mapper

2011-08-08 Thread Phazorx
this is from the entity constructor:

def __init__(self, *, login, password):

this is the test for initialization with positional arguments:

def test_incorrect_instantiation_positional(self):
with self.assertRaises(TypeError):
User(login, password)

It passes like this just fine and if I'd be to call:

User(login, password)

the result is:

TypeError: __init__() takes exactly 1 positional argument (3
given)

IMHO, it works as expected and positional arguments are explicitly
forbidden. Mind you, these tests are not SQLA-aware in any way and
mapper will affect the classes, however I am under impression it is
not meant to use/affect __init__() and nothing should change in this
department.

On Aug 5, 6:03 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 that's actually interesting, does the constructor of your mapped object still 
 obey the same contract that the *, x, y syntax describes ?  or can you 
 suddenly pass first_name, last_name positionally as well ?

 On Aug 5, 2011, at 2:20 AM, Phazorx wrote:



  The patch worked on 0.7.0 and i don't get warning from Python (3.2),
  so it seem to have addressed the issue correctly.
  (Well i don't get same error at least, once i finish with unittests i
  can either confirm or deny lack of side effects)
  Thanks!

  On Jul 29, 6:38 pm, Michael Bayer mike...@zzzcomputing.com wrote:
  On Jul 29, 2011, at 3:45 AM, Phazorx wrote:

  Most of my entities accept various combinations of parameters and it
  makes sense for my to use keyword-only pattern of constructors:

  class Person(Root_Entity):
     def __init__(self, session, *, first_name, last_name):

  class Address(Root_Entity):
     def __init__(self, session, *, street, building, unit=None,
  zip=None, office=None, city=My City, region=None, country=My
  Country):

  however, in this case i get following from python while SQLA figures
  out relationships:
     ValueError: Function has keyword-only arguments or annotations,
  use getfullargspec() API which can support them

  full traceback:http://dpaste.com/hold/581307/

  Everything is peachy as soon as i get rid of *, in constructor
  obviously... but what can i do to preserve such constructors and still
  be able to use SQLA?

  So you're using some Python syntax I've never seen before, let's check 
  (checking...OK its new in Python 3, does not appear to be in the language 
  tutorial either, just in the PEP) and in the first case we'd have to use 
  getfullargspec() in that case when Py3 is in use, however we'd also have 
  to interpret the extended tuple returned by getfullargspec() correctly 
  when we establish instrumentation.

  If the following patch works, then we could commit once a test is written, 
  though looking at it I'm not optimistic that some significant extra work 
  might be needed to do this correctly.   Until then this is an unsupported 
  use case.  Ticket #2237 is addedhttp://www.sqlalchemy.org/trac/ticket/2237.

  diff -r 87a1dc569235 lib/sqlalchemy/util/compat.py
  --- a/lib/sqlalchemy/util/compat.py     Thu Jul 28 11:53:18 2011 -0400
  +++ b/lib/sqlalchemy/util/compat.py     Fri Jul 29 10:35:23 2011 -0400
  @@ -90,6 +90,11 @@
       from urlparse import parse_qsl

   if py3k:
  +    from inspect import getfullargspec as inspect_getfullargspec
  +else:
  +    from inspect import getargspec as inspect_getfullargspec
  +
  +if py3k:
       # they're bringing it back in 3.2.  brilliant !
       def callable(fn):
           return hasattr(fn, '__call__')
  diff -r 87a1dc569235 lib/sqlalchemy/util/langhelpers.py
  --- a/lib/sqlalchemy/util/langhelpers.py        Thu Jul 28 11:53:18 2011 
  -0400
  +++ b/lib/sqlalchemy/util/langhelpers.py        Fri Jul 29 10:35:23 2011 
  -0400
  @@ -15,7 +15,7 @@
   import sys
   import types
   import warnings
  -from compat import update_wrapper, set_types, threading
  +from compat import update_wrapper, set_types, threading, 
  inspect_getfullargspec
   from sqlalchemy import exc

   def _unique_symbols(used, *bases):
  @@ -149,7 +149,7 @@
          'apply_pos': '(self, a, b, c, **d)'}

       
  -    spec = callable(fn) and inspect.getargspec(fn) or fn
  +    spec = callable(fn) and inspect_getfullargspec(fn) or fn
       args = inspect.formatargspec(*spec)
       if spec[0]:
           self_arg = spec[0][0]

  --
  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 
  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 sqlalchemy@googlegroups.com.
  To unsubscribe from this group, send email to 
  sqlalchemy+unsubscr...@googlegroups.com.
  For more options, visit this group 
  

[sqlalchemy] Re: Cascade Deletes

2011-08-08 Thread Aviv Giladi
Stefano,

Thank you again for your time. I am sorry for not posting my actual
code - it is sensitive, therefore I am trying to reproduce the same
issue with different code.

In my __init__ function of my Rating I am setting 3 members that are
objects like so:
self.member = member
These members are objects that have a relationship with Rating.

When I remove these assignments, everything works fine.

Does this ring any bells?

On Aug 7, 1:15 pm, Stefano Fontanelli s.fontane...@asidev.com wrote:
 Il 07/08/11 20.08, Aviv Giladi ha scritto:

  I see.

  Where can I start looking for such an error? What could possibly be
  causing this?

 I'm sorry but I cannot help you without your code... not a similar code
 but THE code which produce that error.

 Regards,
 Stefano.

 --
 Ing. Stefano Fontanelli
 Asidev S.r.l.
 Via Osteria Bianca, 108/A 50053 Empoli (Firenze)
 Tel. (+39) 333 36 53 294   Fax. (+39) 0571 1 979 978
 E-mail: s.fontane...@asidev.com   Web:www.asidev.com
 Skype: stefanofontanelli

-- 
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] Re: Cascade Deletes

2011-08-08 Thread Stefano Fontanelli

Il 08/08/11 22.53, Aviv Giladi ha scritto:

Dear Stefano,

I have been able to create a reproducing project. I am sending it to 
you directly because I was unable to figure out how to attach the test 
file to the message board. I will post our findings there once we are 
done.


The included script includes all my models. I have 1 rating object, 
called Rating, 2 subratings - ProductsRating and 
CustomerServiceRating, and a subrating property - ProductsProperty, 
that is assigned to ProductsRating.


When you run the code I am attaching as is, you will encounter my 
issue (InterfaceError exception).
However, the odd thing is that the following 2 adjustments to the 
script fix the problem:
1) deleting the three lines 126, 127 and 128 causes the script to work 
just fine
2) instead of querying the session for the ProductsProperty, creating 
it with its c'tor makes the script works as well.


I am extremely confused by this. Any help you could give me would be 
beyond appreciated.


Thank you so much,
Aviv



Hi Aviv.

You made a mistake using 'cascade' and your code produces 2 warnings:

SAWarning: On Rating.products_rating, delete-orphan cascade is not 
supported on a many-to-many or many-to-one relationship when 
single_parent is not set.   Set single_parent=True on the relationship().


SAWarning: On Rating.customer_service_rating, delete-orphan cascade is 
not supported on a many-to-many or many-to-one relationship when 
single_parent is not set.   Set single_parent=True on the relationship().



The problem is 'cascade' setting in the following relationships:

products_rating = relationship(ProductsRating, cascade=all, 
delete-orphan, backref=backref(rating, uselist=False))
customer_service_rating = relationship(CustomerServiceRating, 
cascade=all, delete-orphan, backref=backref(rating, uselist=False))


you cannot set 'cascade' in ManyToMany and ManyToOne relationships, to 
do that you must specify 'single_parent=True'.

Check the docs to understand the usage of 'single_parent'.

Otherwise use 'cascade' as follow:

products_rating = relationship(ProductsRating, 
backref=backref(rating, cascade=all, delete-orphan, uselist=False))
customer_service_rating = relationship(CustomerServiceRating, 
backref=backref(rating, cascade=all, delete-orphan, uselist=False))


I don't know the meaning of you model for that reason you must choose 
the right solution.


I attached your script. I fixed it and SQLA doesn't give me any 
InterfaceError.


HINT: when you use the declarative SQLA you don't need to define 
__init__ function in your entities. The default __init__ is often enough.

It is needed when you want a custom behaviour.

Regards,
Stefano.

PS: you are using Pyramid! Great project!
PS2: I send this message in ML to help other users in the future.


--
Ing. Stefano Fontanelli
Asidev S.r.l.
Via Osteria Bianca, 108/A 50053 Empoli (Firenze)
Tel. (+39) 333 36 53 294   Fax. (+39) 0571 1 979 978
E-mail: s.fontane...@asidev.com   Web: www.asidev.com
Skype: stefanofontanelli

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

import transaction
from sqlalchemy import create_engine
from sqlalchemy import *
from sqlalchemy.orm import backref
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker
from zope.sqlalchemy import ZopeTransactionExtension
import datetime
import random
import string

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()

#describes a business
class Business(Base):
	__tablename__ = 'tbl_businesses'
	id = Column(Integer, primary_key=True)
	short_name = Column(Unicode(255), unique=True)
	name = Column(Unicode(255))
	city = Column(Unicode(64))
	state = Column(Unicode(8))
	ratings = relationship(Rating, backref=business)
	
	def __init__(self, short_name, name, city, state):
		self.short_name = short_name
		self.name = name
		self.city = city
		self.state = state

#desribes a user in the system
class User(Base):
	__tablename__ = 'tbl_users'  

	id = Column(Integer, primary_key=True)
	first_name = Column(Unicode(32))
	last_name = Column(Unicode(32))
	email = Column(Unicode(64), unique=True)
	gender = Column(Boolean)
	is_valid = Column(Boolean)
	created = Column(DateTime, default=datetime.datetime.utcnow)
	
	ratings = relationship(Rating, backref=user)

	def __init__(self, first_name, last_name, email, gender):
		self.first_name = first_name
		self.last_name = last_name
		self.email = email
		if gender == male:
			self.gender = True
		else:
			self.gender = False
		self.is_valid = False


#describes a type of user, such as business owner,