From 52d5151aa454fa4a8470849dddb0e49df707f145 Mon Sep 17 00:00:00 2001 From: Jason Kirtland Date: Wed, 31 Oct 2007 03:25:04 +0000 Subject: [PATCH] - Removed unused util.hash() - Fixed __hash__ for association proxy collections --- CHANGES | 13 +++++-- lib/sqlalchemy/ext/associationproxy.py | 30 +++++++-------- lib/sqlalchemy/util.py | 8 +--- test/ext/associationproxy.py | 52 +++++++++++++++----------- 4 files changed, 55 insertions(+), 48 deletions(-) diff --git a/CHANGES b/CHANGES index e44dd18aa7..16bb5aeef9 100644 --- a/CHANGES +++ b/CHANGES @@ -17,14 +17,14 @@ CHANGES - fixed expression translation of text() clauses; this repairs various ORM scenarios where literal text is used for SQL expressions - + - sqlite will reflect "DECIMAL" as a numeric column. - fixed INSERT statements w.r.t. primary key columns that have SQL-expression based default generators on them; SQL expression executes inline as normal but will not trigger a "postfetch" condition for the column, for those DB's who provide it via cursor.lastrowid - + - Renamed the Dialect attribute 'preexecute_sequences' to 'preexecute_pk_sequences'. An attribute proxy is in place for out-of-tree dialects using the old name. @@ -43,13 +43,18 @@ CHANGES - it's an error to session.save() an object which is already persistent [ticket:840] - + - behavior of query.options() is now fully based on paths, i.e. an option such as eagerload_all('x.y.z.y.x') will apply eagerloading to only those paths, i.e. and not 'x.y.x'; eagerload('children.children') applies only to exactly two-levels deep, etc. [ticket:777] -- Made access dao dection more reliable [ticket:828] +- Made access dao detection more reliable [ticket:828] + +- Removed unused util.hash(). + +- Fixed __hash__ for association proxy- these collections are unhashable, + just like their mutable Python counterparts. 0.4.0 ----- diff --git a/lib/sqlalchemy/ext/associationproxy.py b/lib/sqlalchemy/ext/associationproxy.py index 0130721e13..0ee59e3690 100644 --- a/lib/sqlalchemy/ext/associationproxy.py +++ b/lib/sqlalchemy/ext/associationproxy.py @@ -106,7 +106,7 @@ class AssociationProxy(object): Optional, use with proxy_factory. See the _set() method for details. """ - + self.target_collection = targetcollection # backwards compat name... self.value_attr = attr self.creator = creator @@ -141,7 +141,7 @@ class AssociationProxy(object): "scope") return getattr(obj, target) return lazy_collection - + def __get__(self, obj, class_): if obj is None: self.owning_class = class_ @@ -204,12 +204,12 @@ class AssociationProxy(object): if self.proxy_factory: return self.proxy_factory(lazy_collection, creator, self.value_attr) - + if self.getset_factory: getter, setter = self.getset_factory(self.collection_class, self) else: getter, setter = self._default_getset(self.collection_class) - + if self.collection_class is list: return _AssociationList(lazy_collection, creator, getter, setter) elif self.collection_class is dict: @@ -247,7 +247,7 @@ class _AssociationList(object): lazy_collection A callable returning a list-based collection of entities (usually an object attribute managed by a SQLAlchemy relation()) - + creator A function that creates new target entities. Given one parameter: value. The assertion is assumed: @@ -291,7 +291,7 @@ class _AssociationList(object): def __getitem__(self, index): return self._get(self.col[index]) - + def __setitem__(self, index, value): if not isinstance(index, slice): self._set(self.col[index], value) @@ -406,7 +406,7 @@ class _AssociationList(object): def __repr__(self): return repr(list(self)) - def hash(self): + def __hash__(self): raise TypeError("%s objects are unhashable" % type(self).__name__) _NotProvided = object() @@ -420,7 +420,7 @@ class _AssociationDict(object): lazy_collection A callable returning a dict-based collection of entities (usually an object attribute managed by a SQLAlchemy relation()) - + creator A function that creates new target entities. Given two parameters: key and value. The assertion is assumed: @@ -462,7 +462,7 @@ class _AssociationDict(object): def __getitem__(self, key): return self._get(self.col[key]) - + def __setitem__(self, key, value): if key in self.col: self._set(self.col[key], key, value) @@ -535,7 +535,7 @@ class _AssociationDict(object): def popitem(self): item = self.col.popitem() return (item[0], self._get(item[1])) - + def update(self, *a, **kw): if len(a) > 1: raise TypeError('update expected at most 1 arguments, got %i' % @@ -554,7 +554,7 @@ class _AssociationDict(object): def copy(self): return dict(self.items()) - def hash(self): + def __hash__(self): raise TypeError("%s objects are unhashable" % type(self).__name__) class _AssociationSet(object): @@ -567,7 +567,7 @@ class _AssociationSet(object): collection A callable returning a set-based collection of entities (usually an object attribute managed by a SQLAlchemy relation()) - + creator A function that creates new target entities. Given one parameter: value. The assertion is assumed: @@ -707,10 +707,10 @@ class _AssociationSet(object): def issubset(self, other): return util.Set(self).issubset(other) - + def issuperset(self, other): return util.Set(self).issuperset(other) - + def clear(self): self.col.clear() @@ -727,5 +727,5 @@ class _AssociationSet(object): def __repr__(self): return repr(util.Set(self)) - def hash(self): + def __hash__(self): raise TypeError("%s objects are unhashable" % type(self).__name__) diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py index ad3b30e8dd..ab697db0e9 100644 --- a/lib/sqlalchemy/util.py +++ b/lib/sqlalchemy/util.py @@ -112,13 +112,6 @@ def flatten_iterator(x): else: yield elem -def hash(string): - """return an md5 hash of the given string.""" - h = md5.new() - h.update(string) - return h.hexdigest() - - class ArgSingleton(type): instances = {} @@ -530,6 +523,7 @@ class OrderedSet(Set): __isub__ = difference_update + class UniqueAppender(object): """appends items to a collection such that only unique items are added.""" diff --git a/test/ext/associationproxy.py b/test/ext/associationproxy.py index 71c029e071..2accd2fc83 100644 --- a/test/ext/associationproxy.py +++ b/test/ext/associationproxy.py @@ -38,7 +38,7 @@ class _CollectionOperations(PersistTest): collection_class = self.collection_class metadata = MetaData(testbase.db) - + parents_table = Table('Parent', metadata, Column('id', Integer, primary_key=True), Column('name', String)) @@ -51,7 +51,7 @@ class _CollectionOperations(PersistTest): class Parent(object): children = association_proxy('_children', 'name') - + def __init__(self, name): self.name = name @@ -88,7 +88,7 @@ class _CollectionOperations(PersistTest): def _test_sequence_ops(self): Parent, Child = self.Parent, self.Child - + p1 = Parent('P1') self.assert_(not p1._children) @@ -114,7 +114,7 @@ class _CollectionOperations(PersistTest): self.assert_(p1._children[0].name == 'regular') self.assert_(p1._children[1].name == 'proxied') - + del p1._children[1] self.assert_(len(p1._children) == 1) @@ -125,7 +125,7 @@ class _CollectionOperations(PersistTest): self.assert_(len(p1._children) == 0) self.assert_(len(p1.children) == 0) - + p1.children = ['a','b','c'] self.assert_(len(p1._children) == 3) self.assert_(len(p1.children) == 3) @@ -152,7 +152,7 @@ class _CollectionOperations(PersistTest): p1.children.append('changed-in-place') self.assert_(p1.children.count('changed-in-place') == 2) - + p1.children.remove('changed-in-place') self.assert_(p1.children.count('changed-in-place') == 1) @@ -187,7 +187,9 @@ class _CollectionOperations(PersistTest): self.assert_(p1.children == after) self.assert_([c.name for c in p1._children] == after) - + self.assertRaises(TypeError, set, [p1.children]) + + class DefaultTest(_CollectionOperations): def __init__(self, *args, **kw): super(DefaultTest, self).__init__(*args, **kw) @@ -196,6 +198,7 @@ class DefaultTest(_CollectionOperations): def test_sequence_ops(self): self._test_sequence_ops() + class ListTest(_CollectionOperations): def __init__(self, *args, **kw): super(ListTest, self).__init__(*args, **kw) @@ -249,7 +252,7 @@ class CustomDictTest(DictTest): self.assert_(p1._children['a'].name == 'regular') self.assert_(p1._children['b'].name == 'proxied') - + del p1._children['b'] self.assert_(len(p1._children) == 1) @@ -281,7 +284,7 @@ class CustomDictTest(DictTest): p1._children = {} self.assert_(len(p1.children) == 0) - + try: p1._children = [] self.assert_(False) @@ -294,6 +297,9 @@ class CustomDictTest(DictTest): except exceptions.ArgumentError: self.assert_(True) + self.assertRaises(TypeError, set, [p1.children]) + + class SetTest(_CollectionOperations): def __init__(self, *args, **kw): super(SetTest, self).__init__(*args, **kw) @@ -344,7 +350,7 @@ class SetTest(_CollectionOperations): self.assert_(len(p1._children) == 0) self.assert_(len(p1.children) == 0) - + p1.children = ['a','b','c'] self.assert_(len(p1._children) == 3) self.assert_(len(p1.children) == 3) @@ -379,11 +385,11 @@ class SetTest(_CollectionOperations): p1 = self.roundtrip(p1) self.assert_(len(p1.children) == 2) self.assert_(popped not in p1.children) - + p1.children = ['a','b','c'] p1 = self.roundtrip(p1) self.assert_(p1.children == set(['a','b','c'])) - + p1.children.discard('b') p1 = self.roundtrip(p1) self.assert_(p1.children == set(['a', 'c'])) @@ -407,6 +413,8 @@ class SetTest(_CollectionOperations): except exceptions.ArgumentError: self.assert_(True) + self.assertRaises(TypeError, set, [p1.children]) + def test_set_comparisons(self): Parent, Child = self.Parent, self.Child @@ -434,7 +442,7 @@ class SetTest(_CollectionOperations): control.issubset(other)) self.assertEqual(p1.children.issuperset(other), control.issuperset(other)) - + self.assert_((p1.children == other) == (control == other)) self.assert_((p1.children != other) == (control != other)) self.assert_((p1.children < other) == (control < other)) @@ -511,7 +519,7 @@ class CustomObjectTest(_CollectionOperations): class ScalarTest(PersistTest): def test_scalar_proxy(self): metadata = MetaData(testbase.db) - + parents_table = Table('Parent', metadata, Column('id', Integer, primary_key=True), Column('name', String)) @@ -529,7 +537,7 @@ class ScalarTest(PersistTest): creator=lambda v: Child(bar=v)) baz = association_proxy('child', 'baz', creator=lambda v: Child(baz=v)) - + def __init__(self, name): self.name = name @@ -553,7 +561,7 @@ class ScalarTest(PersistTest): id, type_ = obj.id, type(obj) session.clear() return session.query(type_).get(id) - + p = Parent('p') # No child @@ -573,7 +581,7 @@ class ScalarTest(PersistTest): self.assert_(p.foo == 'a') self.assert_(p.bar == 'x') self.assert_(p.baz == 'c') - + p = roundtrip(p) self.assert_(p.foo == 'a') @@ -623,12 +631,12 @@ class ScalarTest(PersistTest): # Ensure an immediate __set__ works. p2 = Parent('p2') p2.bar = 'quux' - + class LazyLoadTest(PersistTest): def setUp(self): metadata = MetaData(testbase.db) - + parents_table = Table('Parent', metadata, Column('id', Integer, primary_key=True), Column('name', String)) @@ -641,7 +649,7 @@ class LazyLoadTest(PersistTest): class Parent(object): children = association_proxy('_children', 'name') - + def __init__(self, name): self.name = name @@ -730,7 +738,7 @@ class LazyLoadTest(PersistTest): self.assert_('_children' in p.__dict__) self.assert_(p._children is not None) - + if __name__ == "__main__": - testbase.main() + testbase.main() -- 2.47.2