예제 #1
0
def anon_term(term, func):
    """lookup or anonomize any term, cache and return cached values

    :param term: term, or string, or date or whatever to anonymize
    :param func: callable to produce appropriate random version of term

    Returns the anonymized version of the term.  Multiple calls with the
    same term return the same anonymized result, regardless of func.

    """
    # difficult to tell if object supports len
    try:
        termlen = len(term)
    except TypeError:
        termlen = 1
    if term is None or termlen == 0:
        return term

    cached = lookup_term(term)
    if cached is not None:
        return cached
    else:
        value = func(term)
        store_term(term, value)
        return value
예제 #2
0
def random_date_delta(delta_ballpark, format=None):
    """generates function to modify a date by some ballpark amount

    :param delta_ballpark: datetime.timedelta to use as ballpark
      shift.  Actual delta randomly generated within 10% of given
      ballpark.  Must be at least 5 years, in either direction, to
      ensure unpredictable shift.
    :param format: optional datetime format string for output.  if
      defined, the input to the generated function is expected to be
      in the same format.

    In order to maintain the strict order of messages, once a delta
    has been calculated for a given delta_ballpark, it guarenteed to
    be reused.  To force a change, provide a different delta_ballpark
    or remove it from the cache.  Look for key values prefixed
    "date_delta".

    returns a function that will modify any given datetime by a fixed
    amount.  enables shifting all datetime fields by the same, yet
    unpredictable amount, to maintain order of events, etc.

    """
    cached_key = "date_delta-%s" % delta_ballpark

    def calculate_delta(ballpark_seconds):
        ballpark_seconds = delta_ballpark.total_seconds()
        if abs(ballpark_seconds) < \
                datetime.timedelta(days=(5 * 365)).total_seconds():
            raise ValueError("insignificant ballpark, increase delta "
                             "magnitude to ensure unpredictable results")
        fudge = .10 * ballpark_seconds
        delta = random.triangular(ballpark_seconds - fudge,
                                  ballpark_seconds + fudge)
        store_term(cached_key, delta)
        return delta

    delta = lookup_term(cached_key)
    if delta is None:
        delta = calculate_delta(delta_ballpark)

    def datetime_shift(initial):
        """returns initial datetime modified by delta

        :param initial: a datetime object to modify, or if format was
          defined when generating this method, a string in said format

        """
        assert(initial)  # don't populate non existing field
        if format:
            try:
                initial = datetime.datetime.strptime(initial, format)
            except ValueError:
                # handly sloppy input when missing time
                if format == '%Y%m%d%H%M%S' and len(initial) == 8:
                    initial = datetime.datetime.strptime(initial, '%Y%m%d')
                else:
                    raise
        result = initial + datetime.timedelta(seconds=delta)
        return result.strftime(format) if format else result

    return datetime_shift