diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-02-29 18:27:17 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-02-29 18:27:17 -0500 |
| commit | 0987f8951637feb48dfbc22508aa46fe59a12f63 (patch) | |
| tree | cae3cd06b2fc598e8842bfff7e26e705a0e94545 /lib/sqlalchemy/orm/util.py | |
| parent | 0536c48dafb670d34fc96d26078b41ed6accf01f (diff) | |
| download | sqlalchemy-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.py | 65 |
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.""" |
