diff options
author | W. Trevor King <wking@drexel.edu> | 2009-06-23 11:35:23 -0400 |
---|---|---|
committer | W. Trevor King <wking@drexel.edu> | 2009-06-23 11:35:23 -0400 |
commit | 83e06581ad007e1a1f27f311ccb3a747f0a81ade (patch) | |
tree | da64348e2f7a638e6f0664d5277aa24f1500e3c5 /libbe/properties.py | |
parent | 37195a33108299504f8d37042dec06df0540d0d2 (diff) | |
download | bugseverywhere-83e06581ad007e1a1f27f311ccb3a747f0a81ade.tar.gz |
Added Bug.extra_strings to support add-on functionality, e.g. `be tag`.
Versioned properties whose data is a mutable type are tricky, since
the simple comparisons we'd been using in
libbe.properties.change_hook_property don't work for mutables. For
now, we avoid that problem by assuming a change happened whenever a
mutable property is set. change_hook_property is a bit untidy at the
moment while I work out how to deal with mutables.
As an example of using Bug.extra_strings to patch on some useful
functionality, I've written becommands/tag.py. I'd suggest future
add-ons (e.g. becommands/depend.py?) use the "<LABEL>:<value>" string
format to keep it easy to sort out which strings belong to which
add-ons. tag.py is still missing command line tag-removal and
tag-searching for `be list'. Perhaps something like
be list --extra-strings TAG:<your-tag>,TAG:<another-tag>,DEPEND:<bug-id>
would be good, although it would requre escaping commas from the tags,
or refusing to allow commas in the tags...
libbe.properties.ValueCheckError also got a minor update so the
printed error message makes sense when raised with allowed being an
iterable (i.e. check_property) or a function
(e.g. fn_checked_property).
All of this digging around turned up a really buggy
libbe.bugdir.MultipleBugMatches. Obviously I had never actually
called it before :p. Should be fixed now.
libbe.comment._set_comment_body has also been normalized to match the
suggested change_hook interface: change_hook(self, old, new).
Although, I'm not sure why it hadn't been causing obvious problems
before, so maybe I'm misunderstanding something about that.
Diffstat (limited to 'libbe/properties.py')
-rw-r--r-- | libbe/properties.py | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/libbe/properties.py b/libbe/properties.py index a8e89fb..9292ad7 100644 --- a/libbe/properties.py +++ b/libbe/properties.py @@ -26,12 +26,15 @@ and for more information on decorators. """ +import types import unittest - class ValueCheckError (ValueError): def __init__(self, name, value, allowed): - msg = "%s not in %s for %s" % (value, allowed, name) + action = "in" # some list of allowed values + if type(allowed) == types.FunctionType: + action = "allowed by" # some allowed-value check function + msg = "%s not %s %s for %s" % (value, action, allowed, name) ValueError.__init__(self, msg) self.name = name self.value = value @@ -258,12 +261,29 @@ def primed_property(primer, initVal=None): return funcs return decorator -def change_hook_property(hook): +def change_hook_property(hook, mutable=False): """ Call the function hook(instance, old_value, new_value) whenever a value different from the current value is set (instance is a a reference to the class instance to which this property belongs). - This is useful for saving changes to disk, etc. + This is useful for saving changes to disk, etc. This function is + called _after_ the new value has been stored, allowing you to + change the stored value if you want. + + If mutable=True, store a string-representation of the old_value + for use in comparisions, since + + >>> a = [] + >>> b = a + >>> b.append(1) + >>> a + [1] + >>> a==b + True + + The string-value-changed test may miss the first write, since + there will not have been an opportunity to cache a string version + of the old value. """ def decorator(funcs): if hasattr(funcs, "__call__"): @@ -273,9 +293,23 @@ def change_hook_property(hook): name = funcs.get("name", "<unknown>") def _fset(self, value): old_value = fget(self) + fset(self, value) + change_detected = False if value != old_value: + change_detected = True + elif mutable == True: + if True: #hasattr(self, "_change_hook_property_mutable_cache_%s" % name): + # compare cached string with new value + #old_string = getattr(self, "_change_hook_property_mutable_cache_%s" % name) + old_string = "dummy" + #print "comparing", name, "mutable strings", old_string, repr(value) + if repr(value) != old_string: + change_detected = True + #print "testing", name, "change hook property", change_detected, value + if change_detected: hook(self, old_value, value) - fset(self, value) + if mutable == True: # cache the new value for next time + setattr(self, "_change_hook_property_mutable_cache_%s" % name, repr(value)) funcs["fset"] = _fset return funcs return decorator |