# Buggy code
def get_dataset(self, dataset_id, ds_info, out=None):
    var_path = ds_info.get("file_key", "{}".format(dataset_id.name))
    dtype = ds_info.get("dtype", np.float32)
    shape = self.get_shape(dataset_id, ds_info)
    file_units = ds_info.get("file_units")
    if file_units is None:
        file_units = self.get(
            var_path + "/attr/units", self.get(var_path + "/attr/Units")
        )
    if file_units is None:
        raise KeyError("File variable '{}' has no units attribute".format(var_path))
    elif file_units == "deg":
        file_units = "degrees"
    elif file_units == "Unitless":
        file_units = "1"

    if out is None:
        out = np.ma.empty(shape, dtype=dtype)
        out.mask = np.zeros(shape, dtype=np.bool)

    valid_min, valid_max = self.get(
        var_path + "/attr/valid_range",
        self.get(var_path + "/attr/ValidRange", (None, None)),
    )
    if valid_min is None or valid_max is None:
        raise KeyError(
            "File variable '{}' has no valid range attribute".format(var_path)
        )
    fill_name = var_path + "/attr/{}".format(self._fill_name)
    if fill_name in self:
        fill_value = self[fill_name]
    else:
        fill_value = None

    out.data[:] = np.require(self[var_path][:], dtype=dtype)
    scale_factor_path = var_path + "/attr/ScaleFactor"
    if scale_factor_path in self:
        scale_factor = self[scale_factor_path]
        scale_offset = self[var_path + "/attr/Offset"]
    else:
        scale_factor = None
        scale_offset = None

    if valid_min is not None and valid_max is not None:
        # the original .cfg/INI based reader only checked valid_max
        out.mask[:] |= (out.data > valid_max) | (out.data < valid_min)
    if fill_value is not None:
        out.mask[:] |= out.data == fill_value

    factors = (scale_factor, scale_offset)
    factors = self.adjust_scaling_factors(factors, file_units, ds_info.get("units"))
    if factors[0] != 1 or factors[1] != 0:
        out.data[:] *= factors[0]
        out.data[:] += factors[1]

    i = getattr(out, "info", {})
    i.update(ds_info)
    i.update(
        {
            "units": ds_info.get("units", file_units),
            "platform": self.platform_name,
            "sensor": self.sensor_name,
            "start_orbit": self.start_orbit_number,
            "end_orbit": self.end_orbit_number,
        }
    )
    i.update(dataset_id.to_dict())
    if "standard_name" not in ds_info:
        i["standard_name"] = self.get(var_path + "/attr/Title", dataset_id.name)
    cls = ds_info.pop("container", Dataset)
    return cls(out.data, mask=out.mask, copy=False, **i)


# Traceback (AttributeError)
[INFO: 2017-12-12 08:14:04 : satpy.writers.cf_writer] Saving datasets to NetCDF4/CF.
[INFO: 2017-12-12 08:14:04 : satpy.writers.cf_writer] No longitude and latitude data to save.
[INFO: 2017-12-12 08:14:04 : satpy.writers.cf_writer] No grid mapping to save.
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-24-58ece08c15f3> in <module>()
----> 1 lcl.save_datasets(writer='cf', filename='/tmp/foo.nc')

/home/lahtinep/Software/pytroll/packages/satpy/satpy/scene.pyc in save_datasets(self, writer, datasets, **kwargs)
632             datasets = self.datasets.values()
633         writer = self.get_writer(writer, **kwargs)
--> 634         writer.save_datasets(datasets, **kwargs)
635
636     def get_writer(self, writer="geotiff", **kwargs):

/home/lahtinep/Software/pytroll/packages/satpy/satpy/writers/cf_writer.pyc in save_datasets(self, datasets, filename, **kwargs)
176                     coords = [line_coord, pixel_coord]
177
--> 178                 domain = cf.Domain(dim=coords,
179                                    aux=aux,
180                                    ref=grid_mapping)

AttributeError: 'module' object has no attribute 'Domain'

# Fixed code
def get_dataset(self, dataset_id, ds_info):
    var_path = ds_info.get("file_key", "{}".format(dataset_id.name))
    metadata = self.get_metadata(dataset_id, ds_info)
    valid_min, valid_max = self.get(
        var_path + "/attr/valid_range",
        self.get(var_path + "/attr/ValidRange", (None, None)),
    )
    if valid_min is None or valid_max is None:
        raise KeyError(
            "File variable '{}' has no valid range attribute".format(var_path)
        )
    fill_name = var_path + "/attr/{}".format(self._fill_name)
    if fill_name in self:
        fill_value = self[fill_name]
    else:
        fill_value = None

    data = self[var_path]
    scale_factor_path = var_path + "/attr/ScaleFactor"
    if scale_factor_path in self:
        scale_factor = self[scale_factor_path]
        scale_offset = self[var_path + "/attr/Offset"]
    else:
        scale_factor = None
        scale_offset = None

    if valid_min is not None and valid_max is not None:
        # the original .cfg/INI based reader only checked valid_max
        data = data.where((data <= valid_max) & (data >= valid_min))
    if fill_value is not None:
        data = data.where(data != fill_value)

    factors = (scale_factor, scale_offset)
    factors = self.adjust_scaling_factors(
        factors, metadata["file_units"], ds_info.get("units")
    )
    if factors[0] != 1 or factors[1] != 0:
        data = data * factors[0] + factors[1]

    data.attrs.update(metadata)
    return data