[sqlalchemy] Re: keyword-only arguments in entity constructor confuse mapper
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
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
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,