summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES46
-rw-r--r--lib/sqlalchemy/orm/scoping.py27
-rw-r--r--test/orm/scoping.py30
3 files changed, 66 insertions, 37 deletions
diff --git a/CHANGES b/CHANGES
index abd018871..73590bcd5 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,36 +7,38 @@ CHANGES
0.5.0rc2
========
- orm
- - Fixed bug involving read/write relation()s that
- contain literal or other non-column expressions
- within their primaryjoin condition equated
- to a foreign key column.
-
- - "non-batch" mode in mapper(), a feature which allows
- mapper extension methods to be called as each instance
- is updated/inserted, now honors the insert order
- of the objects given.
-
- - fixed RLock-related bug in mapper which could deadlock
- upon reentrant mapper compile() calls, something that
- occurs when using declarative constructs inside of
- ForeignKey objects.
+ - Fixed bug involving read/write relation()s that contain
+ literal or other non-column expressions within their
+ primaryjoin condition equated to a foreign key column.
+
+ - "non-batch" mode in mapper(), a feature which allows mapper
+ extension methods to be called as each instance is
+ updated/inserted, now honors the insert order of the objects
+ given.
+
+ - Fixed RLock-related bug in mapper which could deadlock upon
+ reentrant mapper compile() calls, something that occurs when
+ using declarative constructs inside of ForeignKey objects.
- ScopedSession.query_property now accepts a query_cls factory,
overriding the session's configured query_cls.
+ - Fixed shared state bug interfering with ScopedSession.mapper's
+ ability to apply default __init__ implementations on object
+ subclasses.
+
- sql
- - column.in_(someselect) can now be used as
- a columns-clause expression without the subquery
- bleeding into the FROM clause [ticket:1074]
+ - column.in_(someselect) can now be used as a columns-clause
+ expression without the subquery bleeding into the FROM clause
+ [ticket:1074]
- sqlite
- - Overhauled SQLite date/time bind/result processing
- to use regular expressions and format strings, rather
- than strptime/strftime, to generically support
- pre-1900 dates, dates with microseconds. [ticket:968]
+ - Overhauled SQLite date/time bind/result processing to use
+ regular expressions and format strings, rather than
+ strptime/strftime, to generically support pre-1900 dates,
+ dates with microseconds. [ticket:968]
+
-
0.5.0rc1
========
diff --git a/lib/sqlalchemy/orm/scoping.py b/lib/sqlalchemy/orm/scoping.py
index 5dd17a289..b557e0232 100644
--- a/lib/sqlalchemy/orm/scoping.py
+++ b/lib/sqlalchemy/orm/scoping.py
@@ -142,7 +142,7 @@ class _ScopedExt(MapperExtension):
self.context = context
self.validate = validate
self.save_on_init = save_on_init
- self.set_kwargs_on_init = None
+ self.set_kwargs_on_init = True
def validating(self):
return _ScopedExt(self.context, validate=True)
@@ -162,26 +162,23 @@ class _ScopedExt(MapperExtension):
if not 'query' in class_.__dict__:
class_.query = query()
- if self.set_kwargs_on_init is None:
- self.set_kwargs_on_init = class_.__init__ is object.__init__
- if self.set_kwargs_on_init:
- def __init__(self, **kwargs):
- pass
- class_.__init__ = __init__
+ if self.set_kwargs_on_init and class_.__init__ is object.__init__:
+ class_.__init__ = self._default__init__(mapper)
- def init_instance(self, mapper, class_, oldinit, instance, args, kwargs):
- if self.save_on_init:
- session = kwargs.pop('_sa_session', None)
-
- if self.set_kwargs_on_init:
+ def _default__init__(ext, mapper):
+ def __init__(self, **kwargs):
for key, value in kwargs.items():
- if self.validate:
+ if ext.validate:
if not mapper.get_property(key, resolve_synonyms=False,
raiseerr=False):
raise sa_exc.ArgumentError(
"Invalid __init__ argument: '%s'" % key)
- setattr(instance, key, value)
- kwargs.clear()
+ setattr(self, key, value)
+ return __init__
+
+ def init_instance(self, mapper, class_, oldinit, instance, args, kwargs):
+ if self.save_on_init:
+ session = kwargs.pop('_sa_session', None)
if self.save_on_init:
session = session or self.context.registry()
diff --git a/test/orm/scoping.py b/test/orm/scoping.py
index 32e0dedb0..eea855490 100644
--- a/test/orm/scoping.py
+++ b/test/orm/scoping.py
@@ -132,6 +132,36 @@ class ScopedMapperTest(_ScopedTest):
assert hasattr(Baz, 'query')
@testing.resolve_artifact_names
+ def test_default_constructor_state_not_shared(self):
+ scope = scoped_session(sa.orm.sessionmaker())
+
+ class A(object):
+ pass
+ class B(object):
+ def __init__(self):
+ pass
+
+ scope.mapper(A, table1)
+ scope.mapper(B, table2)
+
+ A(foo='bar')
+ self.assertRaises(TypeError, B, foo='bar')
+
+ scope = scoped_session(sa.orm.sessionmaker())
+
+ class C(object):
+ def __init__(self):
+ pass
+ class D(object):
+ pass
+
+ scope.mapper(C, table1)
+ scope.mapper(D, table2)
+
+ self.assertRaises(TypeError, C, foo='bar')
+ D(foo='bar')
+
+ @testing.resolve_artifact_names
def test_validating_constructor(self):
s2 = SomeObject(someid=12)
s3 = SomeOtherObject(someid=123, bogus=345)