# Buggy code
def setval(key, val):
    """
    Set a grains value in the grains config file

    CLI Example:

    .. code-block:: bash

        salt '*' grains.setval key val
        salt '*' grains.setval key "{'sub-key': 'val', 'sub-key2': 'val2'}"
    """
    grains = {}
    if os.path.isfile(__opts__["conf_file"]):
        gfn = os.path.join(os.path.dirname(__opts__["conf_file"]), "grains")
    elif os.path.isdir(__opts__["conf_file"]):
        gfn = os.path.join(__opts__["conf_file"], "grains")
    else:
        gfn = os.path.join(os.path.dirname(__opts__["conf_file"]), "grains")

    if os.path.isfile(gfn):
        with salt.utils.fopen(gfn, "rb") as fp_:
            try:
                grains = yaml.safe_load(fp_.read())
            except Exception as e:
                return "Unable to read existing grains file: {0}".format(e)
        if not isinstance(grains, dict):
            grains = {}
    grains[key] = val
    cstr = yaml.safe_dump(grains, default_flow_style=False)
    with salt.utils.fopen(gfn, "w+") as fp_:
        fp_.write(cstr)
    fn_ = os.path.join(__opts__["cachedir"], "module_refresh")
    with salt.utils.fopen(fn_, "w+") as fp_:
        fp_.write("")
    # Sync the grains
    __salt__["saltutil.sync_grains"]()
    # Return the grain we just set to confirm everything was OK
    return {key: val}


# Traceback (AttributeError)
[ERROR   ] Error in function _master_opts:
Traceback (most recent call last):
File "/usr/lib/pymodules/python2.7/salt/master.py", line 1444, in run_func
ret = getattr(self, func)(load)
File "/usr/lib/pymodules/python2.7/salt/master.py", line 891, in _master_opts
envs = self._file_envs()
File "/usr/lib/pymodules/python2.7/salt/fileserver/__init__.py", line 153, in envs
ret.update(self.servers[fstr]())
File "/usr/lib/pymodules/python2.7/salt/fileserver/hgfs.py", line 176, in envs
tags = repo.get_tags()
AttributeError: 'hgclient' object has no attribute 'get_tags'

# Fixed code
def setval(key, val):
    """
    Set a grains value in the grains config file

    CLI Example:

    .. code-block:: bash

        salt '*' grains.setval key val
        salt '*' grains.setval key "{'sub-key': 'val', 'sub-key2': 'val2'}"
    """
    grains = {}
    if os.path.isfile(__opts__["conf_file"]):
        gfn = os.path.join(os.path.dirname(__opts__["conf_file"]), "grains")
    elif os.path.isdir(__opts__["conf_file"]):
        gfn = os.path.join(__opts__["conf_file"], "grains")
    else:
        gfn = os.path.join(os.path.dirname(__opts__["conf_file"]), "grains")

    if os.path.isfile(gfn):
        with salt.utils.fopen(gfn, "rb") as fp_:
            try:
                grains = yaml.safe_load(fp_.read())
            except Exception as e:
                return "Unable to read existing grains file: {0}".format(e)
        if not isinstance(grains, dict):
            grains = {}
    grains[key] = val
    # Cast defaultdict to dict; is there a more central place to put this?
    yaml.representer.SafeRepresenter.add_representer(
        collections.defaultdict, yaml.representer.SafeRepresenter.represent_dict
    )
    cstr = yaml.safe_dump(grains, default_flow_style=False)
    with salt.utils.fopen(gfn, "w+") as fp_:
        fp_.write(cstr)
    fn_ = os.path.join(__opts__["cachedir"], "module_refresh")
    with salt.utils.fopen(fn_, "w+") as fp_:
        fp_.write("")
    # Sync the grains
    __salt__["saltutil.sync_grains"]()
    # Return the grain we just set to confirm everything was OK
    return {key: val}