Repository: quantopian/zipline
File: zipline/data/hdf5_daily_bars.py (Python)

Code before:
        Construct from a file path.

        Parameters
        ----------
        path : str
            Path to an HDF5 daily pricing file.
        """
        return cls.from_file(h5py.File(path))

    @property
    def countries(self):
        """A set-like object of the country codes supplied by this reader.
        """
        return viewkeys(self._readers)

    def _country_code_for_assets(self, assets):
        country_codes = self._country_map.get(assets)

        if country_codes is not None:
            unique_country_codes = country_codes.dropna().unique()
            num_countries = len(unique_country_codes)
        else:
            num_countries = 0

        if num_countries == 0:
            return self._country_map.iloc[0]
        elif num_countries > 1:
            raise NotImplementedError(
                (
                    'Assets were requested from multiple countries ({}),'
                    ' but multi-country reads are not yet supported.'
                ).format(list(unique_country_codes))
            )

        return np.asscalar(unique_country_codes)

    def load_raw_arrays(self,
                        columns,
                        start_date,
                        end_date,
                        assets):
        """
        Parameters
        ----------
        columns : list of str
           'open', 'high', 'low', 'close', or 'volume'
        start_date: Timestamp
           Beginning of the window range.
        end_date: Timestamp
           End of the window range.
        assets : list of int

Review comment (bug):
Hmm...it feels a little dangerous to return a value here. As a consumer, I'm not sure I'd expect to get a random country back if no assets were found. Another slight worry I have is that this would break in a surprising way if we don't have any readers (we'd KeyError on the .iloc[0] call). 

One alternative would be to raise an error or return a sentinel value here and have the caller decide what to do in this case. For `load_raw_arrays`, for example, we could return an array containing all missing values without ever delegating to any underlying readers (which would work even if we don't have any such readers). I'm 50/50 on whether that compositionality improvement is with the extra complexity in call-sites though. 

Another option would be to just make this an error case, since most likely it's a bug if we hit this path in real-world code.

 Thoughts?

Code after:
            An HDF5 daily pricing file.
        """
        return cls({
            country: HDF5DailyBarReader.from_file(h5_file, country)
            for country in h5_file.keys()
        })

    @classmethod
    def from_path(cls, path):
        """
        Construct from a file path.

        Parameters
        ----------
        path : str
            Path to an HDF5 daily pricing file.
        """
        return cls.from_file(h5py.File(path))

    @property
    def countries(self):
        """A set-like object of the country codes supplied by this reader.
        """
        return viewkeys(self._readers)

    def _country_code_for_assets(self, assets):
        country_codes = self._country_map.get(assets)

        # In some versions of pandas (observed in 0.22), Series.get()
        # returns None if none of the labels are in the index.
        if country_codes is not None:
            unique_country_codes = country_codes.dropna().unique()
            num_countries = len(unique_country_codes)
        else:
            num_countries = 0

        if num_countries == 0:
            raise ValueError('At least one valid asset id is required.')
        elif num_countries > 1:
            raise NotImplementedError(
                (
                    'Assets were requested from multiple countries ({}),'
                    ' but multi-country reads are not yet supported.'
                ).format(list(unique_country_codes))
            )

        return np.asscalar(unique_country_codes)

    def load_raw_arrays(self,
                        columns,
                        start_date,