Skip to content

Unhashable type list error while calling the read_series method in ForecastSolarConnection

Summary

Error encountered when trying to read data using ForecastSolarConnection.read_series in the eta_utility package. The error is related to passing node(s) as lists to the read_series method, which causes a TypeError.

Explain your context

I was attempting to use the ForecastSolarConnection.read_series method to fetch forecast data for a solar node using the following code:


from datetime import datetime
from eta_utility.connectors.forecast_solar import ForecastSolarConnection
from eta_utility.connectors.node import NodeForecastSolar

node_3 = NodeForecastSolar(
    name="east",
    url="https://api.forecast.solar",
    protocol="forecast_solar",
    api_key="REDACTED",
    latitude=49.86381,
    longitude=8.68105,
    declination=[14, 10, 10],
    azimuth=[90, -90, 90],
    kwp=[23.31, 23.31, 23.31],
)

pv_eta = ForecastSolarConnection(url="https://api.forecast.solar", api_key="REDACTED")
nodes_list = [node_3]

pv_eta.read_series(from_time=datetime(2024, 8, 25), to_time=datetime(2024, 8, 28), nodes=nodes_list)

What is the expected correct behavior? What was your goal?

The code should successfully fetch the forecast data from the ForecastSolarConnection and return the appropriate timeseries data without raising an error.

What is the current bug behavior?

Instead of successfully fetching the data, the code raises a TypeError with the following traceback:

TypeError: unhashable type: 'list'

Was there an error message?

Yes, the following error was encountered:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[2], line 23
     19 pv_eta = ForecastSolarConnection(url="https://api.forecast.solar", api_key="87Fpb6aShqa5Hbmf")
     21 nodes_list = [node_3]
---> 23 pv_eta.read_series(from_time=datetime(2024, 8, 25), to_time=datetime(2024, 8, 28), nodes=nodes_list)

File C:\Users\new_folder\.venv\lib\site-packages\eta_utility\connectors\forecast_solar.py:214, in ForecastSolarConnection.read_series(self, from_time, to_time, nodes, interval, **kwargs)
    203 """Download timeseries data from the Forecast.Solar Database
    204 
    205 :param nodes: List of nodes to read values from.
   (...)
    210 :return: Pandas DataFrame containing the data read from the connection.
    211 """
    212 _interval = interval if isinstance(interval, timedelta) else timedelta(seconds=interval)
--> 214 nodes = self._validate_nodes(nodes)
    216 from_time = pd.Timestamp(round_timestamp(from_time, _interval.total_seconds())).tz_convert(self._local_tz)
    217 to_time = pd.Timestamp(round_timestamp(to_time, _interval.total_seconds())).tz_convert(self._local_tz)

File C:\Users\new_folder\.venv\lib\site-packages\eta_utility\connectors\forecast_solar.py:281, in ForecastSolarConnection._validate_nodes(self, nodes)
    280 def _validate_nodes(self, nodes: Nodes | None) -> set[NodeForecastSolar]:  # type: ignore
--> 281     vnodes = super()._validate_nodes(nodes)
    282     _nodes = set()
    283     for node in vnodes:

File C:\Users\new_folder\.venv\lib\site-packages\eta_utility\connectors\base_classes.py:303, in Connection._validate_nodes(self, nodes)
    300         nodes = {nodes}
    302     # If not using preselected nodes from self.selected_nodes, check if nodes correspond to the connection
--> 303     _nodes = {
    304         node for node in nodes if node.protocol == self._PROTOCOL and node.url_parsed.netloc == self._url.netloc
    305     }
    307 # Make sure that some nodes remain after the checks and raise an error if there are none.
    308 if len(_nodes) == 0:

File C:\Users\new_folder\.venv\lib\site-packages\eta_utility\connectors\base_classes.py:304, in <setcomp>(.0)
    300         nodes = {nodes}
    302     # If not using preselected nodes from self.selected_nodes, check if nodes correspond to the connection
    303     _nodes = {
--> 304         node for node in nodes if node.protocol == self._PROTOCOL and node.url_parsed.netloc == self._url.netloc
    305     }
    307 # Make sure that some nodes remain after the checks and raise an error if there are none.
    308 if len(_nodes) == 0:

File <attrs generated hash eta_utility.connectors.node.NodeForecastSolar>:2, in __hash__(self)
      1 def __hash__(self):
----> 2         return hash((
      3                 2836633961041805758,
      4                 self.name,
      5                 self.url,
      6                 self.api_key,
      7                 self.endpoint,
      8                 self.data,
      9                 self.latitude,
     10                 self.longitude,
     11                 self.declination,
     12                 self.azimuth,
     13                 self.kwp,
     14                 self.time,
     15                 self.no_sun,
     16                 self.damping_morning,
     17                 self.damping_evening,
     18                 self.horizon,
     19                 self.inverter,
     20                 self.limit,
     21                 self.start,
     22                 self.transit,
     23                 self.actual,
     24             ))

TypeError: unhashable type: 'list'

Steps to reproduce

  1. Import the necessary modules from eta_utility.
  2. Get the correct API key from Andreas.
  3. Create a NodeForecastSolar object with lists of values for declination and azimuth.
  4. Attempt to use the ForecastSolarConnection.read_series method to fetch data.
  5. Observe the TypeError caused by the unhashable list values in the node object.
Edited by Md Shadman Hasan