Permalink
Browse files

ENH Add CustomHash wrapper

Allow the user to use custom hash functions for their arguments
  • Loading branch information...
1 parent fe028af commit f71cbbc5d1531f0130584c21c3c10c3260fb132f @luispedro committed Dec 19, 2012
Showing with 53 additions and 6 deletions.
  1. +3 −0 ChangeLog
  2. +19 −4 docs/source/tasks.rst
  3. +1 −1 jug/jug_version.py
  4. +2 −0 jug/task.py
  5. +28 −1 jug/utils.py
View
@@ -1,3 +1,6 @@
+version 0.9.3+
+ * Add CustomHash wrapper to set __jug_hash__
+
version 0.9.3 Sun Dec 2 2012 by luispedro
* Fix parsing of ports on redis URL (patch by Alcides Viamontes)
* Make hashing robust to different orders when using randomized hashing
View
@@ -55,8 +55,23 @@ makes jug easy to use but has some drawbacks:
an argument which is an angle and for the purpose of your program all the values
are equivalent modulo 2*pi.
-The solution for this is to provide a ``__jug_hash__`` keyword argument to the Task
-constructor specifying an object that should be used to build the hash instead of
-the function arguments. Or, alternatively, to provide a ``__jug_hash__`` method to
-the problematic arguments: this method should return a string to feed the hash function.
+If you control the types of your arguments, you can add a ``__jug_hash__``
+method to your type directly. This method should return a string::
+
+ class MySpecialThing(object):
+ def __jug_hash__(self):
+ return some_string
+
+Alternatively, you can use ``jug.utils.CustomHash`` in the case where you
+cannot (or rather not) change the types::
+
+ from jug.utils import CustomHash
+ def my_hash_function(x):
+ return some_string_based_on_x
+
+ complex = ...
+ value = CustomHash(complex, my_hash_function)
+
+Now, ``value`` behaves exactly like ``complex``, but it's hash is computed by
+calling ``my_hash_function``.
View
@@ -1 +1 @@
-__version__ = '0.9.3'
+__version__ = '0.9.3+git'
View
@@ -434,6 +434,8 @@ def value(elem):
return tuple([value(e) for e in elem])
elif type(elem) == dict:
return dict((x,value(y)) for x,y in elem.iteritems())
+ elif hasattr(elem, '__jug_value__'):
+ return elem.__jug_value__()
else:
return elem
View
@@ -23,11 +23,12 @@
from __future__ import division
import os
-from .task import Task, Tasklet, TaskGenerator
+from .task import Task, Tasklet, TaskGenerator, value
__all__ = [
'timed_path',
'identity',
+ 'CustomHash',
]
def _return_first(one, two):
@@ -86,3 +87,29 @@ def identity(x):
t.name = 'identity'
return t
+class CustomHash(object):
+ '''
+ value = CustomHash(obj, hash_function)
+
+ Set a custom hash function
+
+ This is an advanced feature and you can shoot yourself in the foot with it.
+ Make sure you know what you are doing. In particular, hash_function should
+ be a strong hash: ``hash_function(obj0) == hash_function(obj1)`` is taken
+ to imply that ``obj0 == obj1``
+
+ Parameters
+ ----------
+ obj : any object
+ hash_function : function
+ This should take your object and return a str
+ '''
+ def __init__(self, obj, hash_function):
+ self.obj = obj
+ self.hash_function = hash_function
+
+ def __jug_hash__(self):
+ return self.hash_function(self.obj)
+
+ def __jug_value__(self):
+ return value(self.obj)

0 comments on commit f71cbbc

Please sign in to comment.