# Buggy code
def _find_dirs(metadata):
    """
    Looks for all the directories in the S3 bucket cache metadata.

    Supports trailing '/' keys (as created by S3 console) as well as
    directories discovered in the path of file keys.
    """

    ret = []
    found = {}

    for bucket_dict in metadata:
        for bucket_name, data in six.iteritems(bucket_dict):
            dirpaths = set()
            for path in [k["Key"] for k in data]:
                prefix = ""
                for part in path.split("/")[:-1]:
                    directory = prefix + part + "/"
                    dirpaths.add(directory)
                    prefix = directory
            if bucket_name not in found:
                found[bucket_name] = True
                ret.append({bucket_name: list(dirpaths)})
            else:
                for bucket in ret:
                    if bucket_name in bucket:
                        bucket[bucket_name] += list(dirpaths)
                        bucket[bucket_name] = list(set(bucket[bucket_name]))
                        break
    return ret


# Traceback (ValueError)
Exception occurred in runner state.orchestrate: Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/salt/client/mixins.py", line 382, in _low
data['return'] = self.functions[fun](*args, **kwargs)
File "/usr/lib/python2.7/site-packages/salt/runners/state.py", line 88, in orchestrate
orchestration_jid=orchestration_jid)
File "/usr/lib/python2.7/site-packages/salt/modules/state.py", line 1098, in sls
initial_pillar=_get_initial_pillar(opts))
File "/usr/lib/python2.7/site-packages/salt/state.py", line 3846, in __init__
BaseHighState.__init__(self, opts)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2721, in __init__
self.avail = self.__gather_avail()
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2730, in __gather_avail
for saltenv in self._get_envs():
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2791, in _get_envs
client_envs = self.client.envs()
File "/usr/lib/python2.7/site-packages/salt/fileclient.py", line 1331, in envs
return self.channel.send(load)
File "/usr/lib/python2.7/site-packages/salt/fileserver/__init__.py", line 892, in send
return self.fs.envs()
File "/usr/lib/python2.7/site-packages/salt/fileserver/__init__.py", line 488, in envs
ret.update(self.servers[fstr](**kwargs))
File "/usr/lib/python2.7/site-packages/salt/fileserver/s3fs.py", line 93, in envs
metadata = _init()
File "/usr/lib/python2.7/site-packages/salt/fileserver/s3fs.py", line 354, in _init
metadata = _read_buckets_cache_file(cache_file)
File "/usr/lib/python2.7/site-packages/salt/fileserver/s3fs.py", line 553, in _read_buckets_cache_file
data = pickle.load(fp_)
File "/usr/lib64/python2.7/pickle.py", line 1378, in load
return Unpickler(file).load()
File "/usr/lib64/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/usr/lib64/python2.7/pickle.py", line 966, in load_string
raise ValueError, "insecure string pickle"
ValueError: insecure string pickle

# Fixed code
def _find_dirs(metadata):
    """
    Looks for all the directories in the S3 bucket cache metadata.

    Supports trailing '/' keys (as created by S3 console) as well as
    directories discovered in the path of file keys.
    """

    ret = []
    found = {}

    for bucket_dict in metadata:
        for bucket_name, data in bucket_dict.items():
            dirpaths = set()
            for path in [k["Key"] for k in data]:
                prefix = ""
                for part in path.split("/")[:-1]:
                    directory = prefix + part + "/"
                    dirpaths.add(directory)
                    prefix = directory
            if bucket_name not in found:
                found[bucket_name] = True
                ret.append({bucket_name: list(dirpaths)})
            else:
                for bucket in ret:
                    if bucket_name in bucket:
                        bucket[bucket_name] += list(dirpaths)
                        bucket[bucket_name] = list(set(bucket[bucket_name]))
                        break
    return ret