def _construct_relative_cache_path(filename, ext, *path_parts, **opts):
    cache_dir = opts.pop('cache_dir', 'cache')
    hash_filename = opts.pop('hash_filename', True)
    hash_method = opts.pop('hash_method', 'md5')
    filename_no_ext, _, _ = filename.rpartition('.')
    filename = u'.'.join((filename_no_ext, ext))
    cache_path = u'/'.join(_strip_str(str(p)) for p in filter(None, path_parts))

    if hash_filename:
        hash = hashlib.new(hash_method)
        hash.update(b(cache_path + filename))
        s = u'{0}/{1}.{2}'.format(cache_dir, hash.hexdigest(), ext)
    else:
        s = os.path.join(cache_dir, cache_path, filename)
    return s
Test that semicolons at the end of a tgrep2 search string won't
dataset/ETHPy150Open jmagnusson/Flask-Resize/flask_resize/__init__.py/_construct_relative_cache_path--crossover with--dataset/ETHPy150Open nltk/nltk/nltk/test/unit/test_tgrep.py/TestSequenceFunctions.test_trailing_semicolon