Repository: Deltares/hydromt

Issue:
Resolve path in data catalog if it contains brackets {}
### HydroMT version checks

- [X] I have checked that this issue has not already been reported.
- [X] I have checked that this bug exists on the latest version of HydroMT.

### Reproducible Example

``` python
from hydromt_wflow import WflowModel
model = WflowModel()
model.data_catalog.get_dataframe("roughness_river_mapping_default")
```


### Current behaviour

```
FileNotFoundError: No such file found: C:\SnapVolumesTemp\MountPoints\{{45c63495-0000-0000-0000-100000000000}}\{{4EB959A1-DAFA-48F1-96BB-E4B67D6DC4E4}}\SVROOT\git\hydromt_wflow\hydromt_wflow\data\wflow\N_river_mapping.csv
```
However, using single brackets does results in correct reading of the csv file. So the solution might need to be searched for in the HydroMT code 

### Desired behaviour

Path should be interpreted correctly.

### Additional context

Might be related to this line in the code (pre-v1, I did not check if the issue still exist with v1) https://github.com/Deltares/hydromt/blob/a707d44497ef493174b76fafde90e45085d78a6c/hydromt/data_adapter/data_adapter.py#L341
I think because we use {} for keywords like variable, year, month. I think this may have been solved in the past but is not working anymore?
See the issue that was opened in hydromt-wflow for more details: https://github.com/Deltares/hydromt_wflow/issues/298

Discussion:
@DirkEilander: This bug does not exist in v1, see test in https://github.com/Deltares/hydromt/blob/91e0cf4855b9f5b8561bfc2b3138a3d597a33063/tests/data_catalog/uri_resolvers/test_convention_resolver.py#L63

In v0.10 it can be reproduces using the test code below and is fixed in 0e394351867e71f47e8e9a9920a0c14900f7cf7e. We need to decide if and when we will release fixes to v0.10, but at least this way it can be installed from the v010 brach directly if users need it.
```
def test_resolve_path_unknown_key(tmp_path):
    # create dummy csv file
    path = tmp_path / "{unknown_key}.csv"
    path.write_text("test")
    # create adapter
    source = DataFrameAdapter(path=path)
    source._resolve_paths()
```@savente93: fixes with #1114 

Solution patch:
diff --git a/hydromt/data_adapter/data_adapter.py b/hydromt/data_adapter/data_adapter.py
index 9c931497..86da5e68 100644
--- a/hydromt/data_adapter/data_adapter.py
+++ b/hydromt/data_adapter/data_adapter.py
@@ -1,4 +1,5 @@
 """DataAdapter class."""
+
 from __future__ import annotations
 
 import logging
@@ -107,7 +108,6 @@ PREPROCESSORS = {
 
 
 class DataAdapter(object, metaclass=ABCMeta):
-
     """General Interface to data source for HydroMT."""
 
     _DEFAULT_DRIVER = None  # placeholder
@@ -325,6 +325,7 @@ class DataAdapter(object, metaclass=ABCMeta):
         known_keys = ["year", "month", "zoom_level", "variable"]
         fns = []
         keys = []
+        unknown_keys = []
         # rebuild path based on arguments and escape unknown keys
         if "{" in str(self.path):
             path = ""
@@ -340,10 +341,15 @@ class DataAdapter(object, metaclass=ABCMeta):
                     path += "*"
                 # escape unknown fields
                 elif key is not None and key not in known_keys:
-                    path = path + "{" + key_str + "}"
+                    unknown_keys.append(key)
+                    path += key_str
                 else:
                     path = path + key_str
                     keys.append(key)
+            if keys and unknown_keys:
+                # escape unknown keys
+                for key in unknown_keys:
+                    path = path.replace("{" + key + "}", "{{" + key + "}}")
         else:
             path = self.path
 


Test patch:
diff --git a/tests/test_data_adapter.py b/tests/test_data_adapter.py
index 1d412e4f..a7f75138 100644
--- a/tests/test_data_adapter.py
+++ b/tests/test_data_adapter.py
@@ -27,6 +27,7 @@ from hydromt.data_adapter import (
     GeoDatasetAdapter,
     RasterDatasetAdapter,
 )
+from hydromt.data_adapter.dataframe import DataFrameAdapter
 from hydromt.data_catalog import DataCatalog
 from hydromt.exceptions import NoDataException
 from hydromt.gis_utils import to_geographic_bbox
@@ -39,25 +40,15 @@ CATALOGDIR = join(dirname(abspath(__file__)), "..", "data", "catalogs")
 
 def test_resolve_path(tmpdir):
     # create dummy files
+    path = join(tmpdir, "{unknown_key}_{zoom_level}_{variable}_{year}_{month:02d}.nc")
     for variable in ["precip", "temp"]:
         for year in [2020, 2021]:
             for month in range(1, 13):
                 fn = join(tmpdir, f"{{unknown_key}}_0_{variable}_{year}_{month:02d}.nc")
                 with open(fn, "w") as f:
                     f.write("")
-    # create data catalog for these files
-    dd = {
-        "test": {
-            "data_type": "RasterDataset",
-            "driver": "netcdf",
-            "path": join(
-                tmpdir, "{unknown_key}_{zoom_level}_{variable}_{year}_{month:02d}.nc"
-            ),
-        }
-    }
-    cat = DataCatalog()
-    cat.from_dict(dd)
-    source = cat.get_source("test")
+    # create adapter
+    source = RasterDatasetAdapter(path=path)
     # test
     fns = source._resolve_paths()
     assert len(fns) == 48
@@ -69,6 +60,15 @@ def test_resolve_path(tmpdir):
         source._resolve_paths(variables=["waves"])
 
 
+def test_resolve_path_unknown_key(tmp_path):
+    # create dummy csv file
+    path = tmp_path / "{unknown_key}.csv"
+    path.write_text("test")
+    # create adapter
+    source = DataFrameAdapter(path=path)
+    source._resolve_paths()
+
+
 def test_rasterdataset(rioda, tmpdir):
     fn_tif = str(tmpdir.join("test.tif"))
     rioda_utm = rioda.raster.reproject(dst_crs="utm")