summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/util.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-02-29 18:27:17 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2012-02-29 18:27:17 -0500
commit0987f8951637feb48dfbc22508aa46fe59a12f63 (patch)
treecae3cd06b2fc598e8842bfff7e26e705a0e94545 /lib/sqlalchemy/orm/util.py
parent0536c48dafb670d34fc96d26078b41ed6accf01f (diff)
downloadsqlalchemy-0987f8951637feb48dfbc22508aa46fe59a12f63.tar.gz
- [bug] Fixed the repr() for CascadeOptions to
include refresh-expire. Also reworked CascadeOptions to be a <frozenset>. [ticket:2417]
Diffstat (limited to 'lib/sqlalchemy/orm/util.py')
-rw-r--r--lib/sqlalchemy/orm/util.py65
1 files changed, 40 insertions, 25 deletions
diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py
index 6ac03d95a..0c5f203a7 100644
--- a/lib/sqlalchemy/orm/util.py
+++ b/lib/sqlalchemy/orm/util.py
@@ -11,6 +11,7 @@ from sqlalchemy.orm.interfaces import MapperExtension, EXT_CONTINUE,\
PropComparator, MapperProperty
from sqlalchemy.orm import attributes, exc
import operator
+import re
mapperlib = util.importlater("sqlalchemy.orm", "mapperlib")
@@ -20,38 +21,52 @@ all_cascades = frozenset(("delete", "delete-orphan", "all", "merge",
_INSTRUMENTOR = ('mapper', 'instrumentor')
-class CascadeOptions(dict):
+class CascadeOptions(frozenset):
"""Keeps track of the options sent to relationship().cascade"""
- def __init__(self, arg=""):
- if not arg:
- values = set()
- else:
- values = set(c.strip() for c in arg.split(','))
-
- for name in ['save-update', 'delete', 'refresh-expire',
- 'merge', 'expunge']:
- boolean = name in values or 'all' in values
- setattr(self, name.replace('-', '_'), boolean)
- if boolean:
- self[name] = True
+ _add_w_all_cascades = all_cascades.difference([
+ 'all', 'none', 'delete-orphan'])
+ _allowed_cascades = all_cascades
+
+ def __new__(cls, arg):
+ values = set([
+ c for c
+ in re.split('\s*,\s*', arg or "")
+ if c
+ ])
+
+ if values.difference(cls._allowed_cascades):
+ raise sa_exc.ArgumentError(
+ "Invalid cascade option(s): %s" %
+ ", ".join([repr(x) for x in
+ sorted(
+ values.difference(cls._allowed_cascades)
+ )])
+ )
+
+ if "all" in values:
+ values.update(cls._add_w_all_cascades)
+ if "none" in values:
+ values.clear()
+ values.discard('all')
+
+ self = frozenset.__new__(CascadeOptions, values)
+ self.save_update = 'save-update' in values
+ self.delete = 'delete' in values
+ self.refresh_expire = 'refresh-expire' in values
+ self.merge = 'merge' in values
+ self.expunge = 'expunge' in values
self.delete_orphan = "delete-orphan" in values
- if self.delete_orphan:
- self['delete-orphan'] = True
if self.delete_orphan and not self.delete:
- util.warn("The 'delete-orphan' cascade option requires "
- "'delete'.")
-
- for x in values:
- if x not in all_cascades:
- raise sa_exc.ArgumentError("Invalid cascade option '%s'" % x)
+ util.warn("The 'delete-orphan' cascade "
+ "option requires 'delete'.")
+ return self
def __repr__(self):
- return "CascadeOptions(%s)" % repr(",".join(
- [x for x in ['delete', 'save_update', 'merge', 'expunge',
- 'delete_orphan', 'refresh-expire']
- if getattr(self, x, False) is True]))
+ return "CascadeOptions(%r)" % (
+ ",".join([x for x in sorted(self)])
+ )
def _validator_events(desc, key, validator):
"""Runs a validation method on an attribute value to be set or appended."""