Repository: openego/eDisGo (language: python)

Issue:
[FEATURE] Implement Database Using Test OEP Environment
**Is your feature request related to a problem? Please describe.**
As we are moving the data to the OpenEnergyPlatform, we should implement the Database by using the test OEP environment.

**Describe the solution you'd like**
The Database should be included correctly, including a dictionary for the query commands. Specifically, we should utilize the configuration file tables with all databases used, including the "dictionary" alias, as demonstrated in the ding0 project.



Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index bed80035..e1385531 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,4 @@ eDisGo.egg-info/
 # exclude .json files in opf
 /edisgo/opf/opf_solutions/*.json
 /edisgo/opf/eDisGo_OPF.jl/.vscode
+.vscode/settings.json
diff --git a/edisgo/io/db.py b/edisgo/io/db.py
index 19dfabcd..e920dee4 100644
--- a/edisgo/io/db.py
+++ b/edisgo/io/db.py
@@ -149,7 +149,7 @@ def ssh_tunnel(cred: dict) -> str:
     return str(server.local_bind_port)
 
 
-def engine(path: Path | str, ssh: bool = False) -> Engine:
+def engine(path: Path | str = None, ssh: bool = False) -> Engine:
     """
     Engine for local or remote database.
 
@@ -167,16 +167,15 @@ def engine(path: Path | str, ssh: bool = False) -> Engine:
         Database engine
 
     """
-    cred = credentials(path=path)
 
     if not ssh:
+        database_url = "toep.iks.cs.ovgu.de"
         return create_engine(
-            f"postgresql+psycopg2://{cred['POSTGRES_USER']}:"
-            f"{cred['POSTGRES_PASSWORD']}@{cred['HOST']}:"
-            f"{cred['PORT']}/{cred['POSTGRES_DB']}",
+            "postgresql+oedialect://:@" f"{database_url}",
             echo=False,
         )
 
+    cred = credentials(path=path)
     local_port = ssh_tunnel(cred)
 
     return create_engine(
diff --git a/edisgo/io/dsm_import.py b/edisgo/io/dsm_import.py
index 648ae503..6cfdafa8 100644
--- a/edisgo/io/dsm_import.py
+++ b/edisgo/io/dsm_import.py
@@ -6,13 +6,13 @@
 
 import numpy as np
 import pandas as pd
-import saio
 
 from sqlalchemy.engine.base import Engine
 
 from edisgo.io.db import session_scope_egon_data
 from edisgo.io.timeseries_import import _timeindex_helper_func
 from edisgo.tools import tools
+from edisgo.tools.config import Config
 
 if TYPE_CHECKING:
     from edisgo import EDisGo
@@ -65,7 +65,7 @@ def oedb(
     dsm_cts = get_profile_cts(edisgo_obj, scenario, engine)
     ind_loads = edisgo_obj.topology.loads_df[
         (edisgo_obj.topology.loads_df.type == "conventional_load")
-        & (edisgo_obj.topology.loads_df.sector == "industry")
+        & (edisgo_obj.topology.loads_df.sector == "industrial")
     ]
     dsm_ind = get_profiles_per_industrial_load(
         ind_loads.building_id.unique(), scenario, engine
@@ -124,17 +124,27 @@ def get_profiles_per_industrial_load(
         column names are site ID as integer.
 
     """
-    saio.register_schema("demand", engine)
-    from saio.demand import (
-        egon_demandregio_sites_ind_electricity_dsm_timeseries as sites_ind_dsm_ts,
-    )
-    from saio.demand import (
+
+    config = Config()
+    (
+        sites_ind_dsm_ts,
         egon_osm_ind_load_curves_individual_dsm_timeseries,
         egon_sites_ind_load_curves_individual_dsm_timeseries,
+    ) = config.import_tables_from_oep(
+        engine,
+        [
+            "egon_demandregio_sites_ind_electricity_dsm_timeseries",
+            "egon_osm_ind_load_curves_individual_dsm_timeseries",
+            "egon_sites_ind_load_curves_individual_dsm_timeseries",
+        ],
+        "demand",
     )
 
     dsm_dict = {}
-
+    if len(load_ids) == 0:
+        for dsm_profile in ["e_min", "e_max", "p_min", "p_max"]:
+            dsm_dict[dsm_profile] = pd.DataFrame()
+        return dsm_dict
     with session_scope_egon_data(engine) as session:
         query = session.query(
             egon_sites_ind_load_curves_individual_dsm_timeseries.site_id,
@@ -160,7 +170,6 @@ def get_profiles_per_industrial_load(
             sites_ind_dsm_ts.scn_name == scenario,
             sites_ind_dsm_ts.industrial_sites_id.in_(load_ids),
         )
-
         df_sites_2 = pd.read_sql(sql=query.statement, con=engine)
 
     with session_scope_egon_data(engine) as session:
@@ -226,8 +235,10 @@ def get_profile_cts(
     egon_data and ding0.
 
     """
-    saio.register_schema("demand", engine)
-    from saio.demand import egon_etrago_electricity_cts_dsm_timeseries
+    config = Config()
+    (egon_etrago_electricity_cts_dsm_timeseries,) = config.import_tables_from_oep(
+        engine, ["egon_etrago_electricity_cts_dsm_timeseries"], "demand"
+    )
 
     # get data
     dsm_dict = {}
diff --git a/edisgo/io/electromobility_import.py b/edisgo/io/electromobility_import.py
index 88852959..83dc68af 100644
--- a/edisgo/io/electromobility_import.py
+++ b/edisgo/io/electromobility_import.py
@@ -10,13 +10,13 @@
 
 import numpy as np
 import pandas as pd
-import saio
 
 from numpy.random import default_rng
 from sklearn import preprocessing
 from sqlalchemy.engine.base import Engine
 
 from edisgo.io.db import get_srid_of_db_table, session_scope_egon_data
+from edisgo.tools.config import Config
 
 if "READTHEDOCS" not in os.environ:
     import geopandas as gpd
@@ -1217,8 +1217,10 @@ def simbev_config_from_oedb(
         more information.
 
     """
-    saio.register_schema("demand", engine)
-    from saio.demand import egon_ev_metadata
+    config = Config()
+    (egon_ev_metadata,) = config.import_tables_from_oep(
+        engine, ["egon_ev_metadata"], "demand"
+    )
 
     with session_scope_egon_data(engine) as session:
         query = session.query(egon_ev_metadata).filter(
@@ -1252,8 +1254,10 @@ def potential_charging_parks_from_oedb(
         for more information.
 
     """
-    saio.register_schema("grid", engine)
-    from saio.grid import egon_emob_charging_infrastructure
+    config = Config()
+    (egon_emob_charging_infrastructure,) = config.import_tables_from_oep(
+        engine, ["egon_emob_charging_infrastructure"], "grid"
+    )
 
     crs = edisgo_obj.topology.grid_district["srid"]
 
@@ -1308,9 +1312,10 @@ def charging_processes_from_oedb(
         more information.
 
     """
-
-    saio.register_schema("demand", engine)
-    from saio.demand import egon_ev_mv_grid_district, egon_ev_trip
+    config = Config()
+    egon_ev_mv_grid_district, egon_ev_trip = config.import_tables_from_oep(
+        engine, ["egon_ev_mv_grid_district", "egon_ev_trip"], "demand"
+    )
 
     # get EV pool in grid
     scenario_variation = {"eGon2035": "NEP C 2035", "eGon100RE": "Reference 2050"}
diff --git a/edisgo/io/generators_import.py b/edisgo/io/generators_import.py
index 281e78a0..ed72c4f8 100755
--- a/edisgo/io/generators_import.py
+++ b/edisgo/io/generators_import.py
@@ -8,13 +8,13 @@
 
 import numpy as np
 import pandas as pd
-import saio
 
 from sqlalchemy import func
 from sqlalchemy.engine.base import Engine
 
 from edisgo.io.db import get_srid_of_db_table, session_scope_egon_data
 from edisgo.tools import session_scope
+from edisgo.tools.config import Config
 from edisgo.tools.geo import find_nearest_bus, proj2equidistant
 from edisgo.tools.tools import (
     determine_bus_voltage_level,
@@ -937,11 +937,15 @@ def _get_egon_chp_plants():
             ).to_crs(srid_edisgo)
         return chp_gdf
 
-    saio.register_schema("supply", engine)
-    from saio.supply import (
+    config = Config()
+    (
         egon_chp_plants,
         egon_power_plants,
         egon_power_plants_pv_roof_building,
+    ) = config.import_tables_from_oep(
+        engine,
+        ["egon_chp_plants", "egon_power_plants", "egon_power_plants_pv_roof_building"],
+        "supply",
     )
 
     # get generator data from database
diff --git a/edisgo/io/heat_pump_import.py b/edisgo/io/heat_pump_import.py
index 69133ca1..840c386b 100644
--- a/edisgo/io/heat_pump_import.py
+++ b/edisgo/io/heat_pump_import.py
@@ -4,11 +4,11 @@
 
 import numpy as np
 import pandas as pd
-import saio
 
 from sqlalchemy import func
 
 from edisgo.io import db
+from edisgo.tools.config import Config
 from edisgo.tools.tools import (
     determine_bus_voltage_level,
     determine_grid_integration_voltage_level,
@@ -267,24 +267,33 @@ def _get_individual_heat_pump_capacity():
         else:
             return np.sum(cap)
 
-    saio.register_schema("demand", engine)
-    from saio.demand import egon_district_heating_areas, egon_hp_capacity_buildings
-
-    saio.register_schema("supply", engine)
-    from saio.supply import (
+    config = Config()
+    (
+        egon_district_heating_areas,
+        egon_hp_capacity_buildings,
+    ) = config.import_tables_from_oep(
+        engine, ["egon_district_heating_areas", "egon_hp_capacity_buildings"], "demand"
+    )
+    (
         egon_district_heating,
         egon_era5_weather_cells,
         egon_individual_heating,
+    ) = config.import_tables_from_oep(
+        engine,
+        ["egon_district_heating", "egon_era5_weather_cells", "egon_individual_heating"],
+        "supply",
     )
-
-    saio.register_schema("boundaries", engine)
-    from saio.boundaries import (
+    (
         egon_map_zensus_mvgd_buildings,
         egon_map_zensus_weather_cell,
+    ) = config.import_tables_from_oep(
+        engine,
+        ["egon_map_zensus_mvgd_buildings", "egon_map_zensus_weather_cell"],
+        "boundaries",
+    )
+    egon_etrago_bus, egon_etrago_link = config.import_tables_from_oep(
+        engine, ["egon_etrago_bus", "egon_etrago_link"], "grid"
     )
-
-    saio.register_schema("grid", engine)
-    from saio.grid import egon_etrago_bus, egon_etrago_link
 
     building_ids = edisgo_object.topology.loads_df.building_id.unique()
     mv_grid_geom_srid = edisgo_object.topology.grid_district["srid"]
@@ -604,8 +613,10 @@ def efficiency_resistive_heaters_oedb(scenario, engine):
         given in p.u.
 
     """
-    saio.register_schema("scenario", engine)
-    from saio.scenario import egon_scenario_parameters
+    config = Config()
+    (egon_scenario_parameters,) = config.import_tables_from_oep(
+        engine, ["egon_scenario_parameters"], "scenario"
+    )
 
     # get cop from database
     with db.session_scope_egon_data(engine) as session:
diff --git a/edisgo/io/storage_import.py b/edisgo/io/storage_import.py
index f9e532f8..2ba1716c 100644
--- a/edisgo/io/storage_import.py
+++ b/edisgo/io/storage_import.py
@@ -6,11 +6,11 @@
 from typing import TYPE_CHECKING
 
 import pandas as pd
-import saio
 
 from sqlalchemy.engine.base import Engine
 
 from edisgo.io.db import session_scope_egon_data
+from edisgo.tools.config import Config
 from edisgo.tools.tools import (
     determine_bus_voltage_level,
     determine_grid_integration_voltage_level,
@@ -49,8 +49,10 @@ def home_batteries_oedb(
         units.
 
     """
-    saio.register_schema("supply", engine)
-    from saio.supply import egon_home_batteries
+    config = Config()
+    (egon_home_batteries,) = config.import_tables_from_oep(
+        engine, ["egon_home_batteries"], "supply"
+    )
 
     with session_scope_egon_data(engine) as session:
         query = (
diff --git a/edisgo/io/timeseries_import.py b/edisgo/io/timeseries_import.py
index 6c66f33a..c26e22ef 100644
--- a/edisgo/io/timeseries_import.py
+++ b/edisgo/io/timeseries_import.py
@@ -6,7 +6,6 @@
 
 import numpy as np
 import pandas as pd
-import saio
 
 from demandlib import bdew as bdew
 from demandlib import particular_profiles as profiles
@@ -15,6 +14,7 @@
 
 from edisgo.io.db import session_scope_egon_data
 from edisgo.tools import session_scope, tools
+from edisgo.tools.config import Config
 
 if "READTHEDOCS" not in os.environ:
     from egoio.db_tables import model_draft, supply
@@ -187,8 +187,10 @@ def feedin_oedb(
         edisgo_object, engine=engine
     )
 
-    saio.register_schema("supply", engine)
-    from saio.supply import egon_era5_renewable_feedin
+    config = Config()
+    (egon_era5_renewable_feedin,) = config.import_tables_from_oep(
+        engine, ["egon_era5_renewable_feedin"], "supply"
+    )
 
     with session_scope_egon_data(engine) as session:
         query = (
@@ -354,8 +356,10 @@ def cop_oedb(edisgo_object, engine, weather_cell_ids, timeindex=None):
         edisgo_object, timeindex, default_year=2011, allow_leap_year=False
     )
 
-    saio.register_schema("supply", engine)
-    from saio.supply import egon_era5_renewable_feedin
+    config = Config()
+    (egon_era5_renewable_feedin,) = config.import_tables_from_oep(
+        engine, ["egon_era5_renewable_feedin"], "supply"
+    )
 
     # get cop from database
     with session_scope_egon_data(engine) as session:
@@ -650,8 +654,10 @@ def _get_zensus_cells_of_buildings(building_ids, engine):
         zensus cell ID in column 'zensus_id' (as integer).
 
     """
-    saio.register_schema("boundaries", engine)
-    from saio.boundaries import egon_map_zensus_mvgd_buildings
+    config = Config()
+    (egon_map_zensus_mvgd_buildings,) = config.import_tables_from_oep(
+        engine, ["egon_map_zensus_mvgd_buildings"], "boundaries"
+    )
 
     with session_scope_egon_data(engine) as session:
         query = session.query(
@@ -828,16 +834,25 @@ def _get_daily_demand_share(zensus_ids):
             df = pd.read_sql(query.statement, query.session.bind, index_col=None)
         return df
 
-    saio.register_schema("demand", engine)
-    from saio.demand import egon_daily_heat_demand_per_climate_zone as daily_heat_demand
-    from saio.demand import (
+    config = Config()
+    (
+        daily_heat_demand,
         egon_heat_idp_pool,
         egon_heat_timeseries_selected_profiles,
         egon_peta_heat,
+    ) = config.import_tables_from_oep(
+        engine,
+        [
+            "egon_daily_heat_demand_per_climate_zone",
+            "egon_heat_idp_pool",
+            "egon_heat_timeseries_selected_profiles",
+            "egon_peta_heat",
+        ],
+        "demand",
+    )
+    (egon_map_zensus_climate_zones,) = config.import_tables_from_oep(
+        engine, ["egon_map_zensus_climate_zones"], "boundaries"
     )
-
-    saio.register_schema("boundaries", engine)
-    from saio.boundaries import egon_map_zensus_climate_zones
 
     # get zensus cells
     zensus_cells_df = _get_zensus_cells_of_buildings(building_ids, engine)
@@ -925,8 +940,10 @@ def get_district_heating_heat_demand_profiles(district_heating_ids, scenario, en
         and column names are district heating network ID as integer.
 
     """
-    saio.register_schema("demand", engine)
-    from saio.demand import egon_timeseries_district_heating
+    config = Config()
+    (egon_timeseries_district_heating,) = config.import_tables_from_oep(
+        engine, ["egon_timeseries_district_heating"], "demand"
+    )
 
     with session_scope_egon_data(engine) as session:
         query = session.query(
@@ -978,8 +995,10 @@ def get_cts_profiles_per_building(edisgo_obj, scenario, sector, engine):
         column names are building ID as integer.
 
     """
-    saio.register_schema("boundaries", engine)
-    from saio.boundaries import egon_map_zensus_mvgd_buildings
+    config = Config()
+    (egon_map_zensus_mvgd_buildings,) = config.import_tables_from_oep(
+        engine, ["egon_map_zensus_mvgd_buildings"], "boundaries"
+    )
 
     # get MV grid IDs of CTS loads
     cts_loads = edisgo_obj.topology.loads_df[
@@ -1133,12 +1152,21 @@ def _get_total_heat_demand_grid():
             df = pd.read_sql(query.statement, engine, index_col=None)
         return df.demand.sum()
 
-    saio.register_schema("demand", engine)
+    config = Config()
+
+    # saio.register_schema("demand", engine)
 
     if sector == "electricity":
-        from saio.demand import (
+        (
             egon_cts_electricity_demand_building_share,
             egon_etrago_electricity_cts,
+        ) = config.import_tables_from_oep(
+            engine,
+            [
+                "egon_cts_electricity_demand_building_share",
+                "egon_etrago_electricity_cts",
+            ],
+            "demand",
         )
 
         df_cts_substation_profiles = _get_substation_profile()
@@ -1147,15 +1175,22 @@ def _get_total_heat_demand_grid():
         df_demand_share = _get_demand_share()
 
     elif sector == "heat":
-        from saio.demand import (
+        (
             egon_cts_heat_demand_building_share,
             egon_etrago_heat_cts,
             egon_peta_heat,
+        ) = config.import_tables_from_oep(
+            engine,
+            [
+                "egon_cts_heat_demand_building_share",
+                "egon_etrago_heat_cts",
+                "egon_peta_heat",
+            ],
+            "demand",
+        )
+        (egon_map_zensus_grid_districts,) = config.import_tables_from_oep(
+            engine, ["egon_map_zensus_grid_districts"], "boundaries"
         )
-
-        saio.register_schema("boundaries", engine)
-        from saio.boundaries import egon_map_zensus_grid_districts
-
         df_cts_substation_profiles = _get_substation_profile()
         if df_cts_substation_profiles.empty:
             return
@@ -1295,13 +1330,19 @@ def _get_profiles(profile_ids):
 
         return df_converted
 
-    saio.register_schema("demand", engine)
-    from saio.demand import (
-        egon_household_electricity_profile_in_census_cell as hh_profile,
-    )
-    from saio.demand import (
+    config = Config()
+    (
+        hh_profile,
         egon_household_electricity_profile_of_buildings,
         iee_household_load_profiles,
+    ) = config.import_tables_from_oep(
+        engine,
+        [
+            "egon_household_electricity_profile_in_census_cell",
+            "egon_household_electricity_profile_of_buildings",
+            "iee_household_load_profiles",
+        ],
+        "demand",
     )
 
     # get zensus cells of buildings
@@ -1412,10 +1453,17 @@ def _get_load_curves_areas(site_ids):
             )
         return pd.read_sql(query.statement, engine, index_col=None)
 
-    saio.register_schema("demand", engine)
-    from saio.demand import (
+    config = Config()
+    (
         egon_osm_ind_load_curves_individual,
         egon_sites_ind_load_curves_individual,
+    ) = config.import_tables_from_oep(
+        engine,
+        [
+            "egon_osm_ind_load_curves_individual",
+            "egon_sites_ind_load_curves_individual",
+        ],
+        "demand",
     )
 
     # get profiles of sites and OSM areas
diff --git a/edisgo/tools/config.py b/edisgo/tools/config.py
index 7494943a..0341299f 100644
--- a/edisgo/tools/config.py
+++ b/edisgo/tools/config.py
@@ -20,6 +20,7 @@
 
 import copy
 import datetime
+import importlib
 import json
 import logging
 import os
@@ -28,8 +29,16 @@
 from glob import glob
 from zipfile import ZipFile
 
+import oedialect  # noqa: F401
+import saio
+import sqlalchemy as sa
+
+from saio import register_schema
+
 import edisgo
 
+from edisgo.io.db import session_scope_egon_data
+
 logger = logging.getLogger(__name__)
 
 try:
@@ -129,6 +138,104 @@ def __init__(self, **kwargs):
                 filename=kwargs.get("json_filename", None),
                 from_zip_archive=kwargs.get("from_zip_archive", False),
             )
+        self._config_dict = {}
+
+    @property
+    def db_table_mapping(self):
+        if not self._config_dict.get("db_table_mapping"):
+            self._set_db_mappings()
+        return self._config_dict.get("db_table_mapping", {})
+
+    @db_table_mapping.setter
+    def db_table_mapping(self, value):
+        self._config_dict["db_table_mapping"] = value
+
+    @property
+    def db_schema_mapping(self):
+        if not self._config_dict.get("db_schema_mapping"):
+            self._set_db_mappings()
+        return self._config_dict.get("db_schema_mapping", {})
+
+    @db_schema_mapping.setter
+    def db_schema_mapping(self, value):
+        self._config_dict["db_schema_mapping"] = value
+
+    def _set_db_mappings(self) -> None:
+        """
+        Sets the database table and schema mappings by retrieving alias dictionaries.
+        """
+        name_mapping, schema_mapping = self.get_database_alias_dictionaries()
+        self.db_table_mapping = name_mapping
+        self.db_schema_mapping = schema_mapping
+
+    def get_database_alias_dictionaries(self) -> tuple[dict[str, str], dict[str, str]]:
+        """
+        Retrieves the database alias dictionaries for table and schema mappings.
+
+        Returns
+        -------
+        tuple
+            A tuple containing two dictionaries:
+            - name_mapping: A dictionary mapping source table names to target table
+                names.
+            - schema_mapping: A dictionary mapping source schema names to target schema
+                names.
+        """
+        OEP_CONNECTION = "postgresql+oedialect://:@{platform}"
+        platform = "toep.iks.cs.ovgu.de"
+        conn_str = OEP_CONNECTION.format(platform=platform)
+        engine = sa.create_engine(conn_str)
+        dictionary_schema_name = (
+            "model_draft"  # Replace with the actual schema name if needed
+        )
+        dictionary_module_name = f"saio.{dictionary_schema_name}"
+        register_schema(dictionary_schema_name, engine)
+        dictionary_table_name = "edut_00"
+        dictionary_table = importlib.import_module(dictionary_module_name).__getattr__(
+            dictionary_table_name
+        )
+        with session_scope_egon_data(engine) as session:
+            query = session.query(dictionary_table)
+            dictionary_entries = query.all()
+            name_mapping = {
+                entry.source_name: entry.target_name for entry in dictionary_entries
+            }
+            schema_mapping = {
+                entry.source_schema: getattr(entry, "target_schema", "model_draft")
+                for entry in dictionary_entries
+            }
+
+        return name_mapping, schema_mapping
+
+    def import_tables_from_oep(
+        self, engine: sa.engine.Engine, table_names: list[str], schema_name: str
+    ) -> list[sa.Table]:
+        """
+        Imports tables from the OEP database based on the provided table names and
+        schema name.
+
+        Parameters
+        ----------
+        engine : sqlalchemy.engine.Engine
+            The SQLAlchemy engine to use for database connection.
+        table_names : list of str
+            List of table names to import.
+        schema_name : str
+            The schema name to use for importing tables.
+
+        Returns
+        -------
+        list of sqlalchemy.Table
+            A list of SQLAlchemy Table objects corresponding to the imported tables.
+        """
+        schema = self.db_schema_mapping.get(schema_name)
+        saio.register_schema(schema, engine)
+        tables = []
+        for table in table_names:
+            table = self.db_table_mapping.get(table)
+            module_name = f"saio.{schema}"
+            tables.append(importlib.import_module(module_name).__getattr__(table))
+        return tables
 
     def from_cfg(self, config_path=None):
         """
@@ -199,7 +306,10 @@ def from_cfg(self, config_path=None):
             config_dict["demandlib"]["day_end"].hour,
             config_dict["demandlib"]["day_end"].minute,
         )
-
+        (
+            config_dict["db_tables_dict"],
+            config_dict["db_schema_dict"],
+        ) = self.get_database_alias_dictionaries()
         return config_dict
 
     def to_json(self, directory, filename=None):
diff --git a/edisgo/tools/tools.py b/edisgo/tools/tools.py
index 061e02ed..66353c55 100644
--- a/edisgo/tools/tools.py
+++ b/edisgo/tools/tools.py
@@ -10,13 +10,13 @@
 import networkx as nx
 import numpy as np
 import pandas as pd
-import saio
 
 from sqlalchemy.engine.base import Engine
 
 from edisgo.flex_opt import exceptions, q_control
 from edisgo.io.db import session_scope_egon_data, sql_grid_geom, sql_intersects
 from edisgo.tools import session_scope
+from edisgo.tools.config import Config
 
 if "READTHEDOCS" not in os.environ:
     from egoio.db_tables import climate
@@ -741,8 +741,10 @@ def get_weather_cells_intersecting_with_grid_district(
             ).filter(sql_intersects(table.geom, sql_geom, srid))
             weather_cells = pd.read_sql(sql=query.statement, con=query.session.bind).gid
     else:
-        saio.register_schema("supply", engine)
-        from saio.supply import egon_era5_weather_cells
+        config = Config()
+        (egon_era5_weather_cells,) = config.import_tables_from_oep(
+            engine, ["egon_era5_weather_cells"], "supply"
+        )
 
         with session_scope_egon_data(engine=engine) as session:
             query = session.query(


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
index 998adaeb..9be426c0 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -29,16 +29,17 @@ def pytest_configure(config):
         os.path.realpath(os.path.dirname(__file__)), "data/tracbev_example_scenario"
     )
 
-    pytest.egon_data_config_yml = os.path.join(
-        os.path.realpath(os.path.dirname(os.path.dirname(__file__))),
-        "egon-data.configuration.yaml",
-    )
+    # pytest.egon_data_config_yml = os.path.join(
+    #     "path/to/ssh/config.yml",
+    # )
+
+    pytest.engine = engine()
 
     config.addinivalue_line("markers", "slow: mark test as slow to run")
     config.addinivalue_line("markers", "local: mark test as local to run")
 
-    if config.getoption("--runlocal"):
-        pytest.engine = engine(path=pytest.egon_data_config_yml, ssh=True)
+    # if config.getoption("--runlocal"):
+    #     pytest.engine_local = engine(path=pytest.egon_data_config_yml, ssh=False)
 
 
 def pytest_addoption(parser):
diff --git a/tests/io/test_dsm_import.py b/tests/io/test_dsm_import.py
index c9ca78fb..d2f595e6 100644
--- a/tests/io/test_dsm_import.py
+++ b/tests/io/test_dsm_import.py
@@ -5,7 +5,6 @@
 
 
 class TestDSMImport:
-    @pytest.mark.local
     def test_oedb(self):
         # test without industrial load
         edisgo_object = EDisGo(
@@ -15,7 +14,7 @@ def test_oedb(self):
             edisgo_object, scenario="eGon2035", engine=pytest.engine
         )
         for dsm_profile in ["e_max", "e_min", "p_max", "p_min"]:
-            assert dsm_profiles[dsm_profile].shape == (8760, 85)
+            assert dsm_profiles[dsm_profile].shape == (8760, 87)
         assert (dsm_profiles["p_min"] <= 0.0).all().all()
         assert (dsm_profiles["e_min"] <= 0.0).all().all()
         assert (dsm_profiles["p_max"] >= 0.0).all().all()
@@ -26,21 +25,20 @@ def test_oedb(self):
             (edisgo_object.topology.loads_df.type == "conventional_load")
             & (edisgo_object.topology.loads_df.sector == "cts")
         ].index[0]
-        edisgo_object.topology.loads_df.at[dsm_load, "sector"] = "industry"
+        edisgo_object.topology.loads_df.at[dsm_load, "sector"] = "industrial"
         edisgo_object.topology.loads_df.at[dsm_load, "building_id"] = 1
 
         dsm_profiles = dsm_import.oedb(
             edisgo_object, scenario="eGon2035", engine=pytest.engine
         )
         for dsm_profile in ["e_max", "e_min", "p_max", "p_min"]:
-            assert dsm_profiles[dsm_profile].shape == (8760, 85)
+            assert dsm_profiles[dsm_profile].shape == (8760, 87)
             assert dsm_load in dsm_profiles[dsm_profile].columns
         assert (dsm_profiles["p_min"] <= 0.0).all().all()
         assert (dsm_profiles["e_min"] <= 0.0).all().all()
         assert (dsm_profiles["p_max"] >= 0.0).all().all()
         assert (dsm_profiles["e_max"] >= 0.0).all().all()
 
-    @pytest.mark.local
     def test_get_profiles_per_industrial_load(self):
         dsm_profiles = dsm_import.get_profiles_per_industrial_load(
             load_ids=[15388, 241, 1], scenario="eGon2035", engine=pytest.engine
@@ -58,7 +56,6 @@ def test_get_profiles_per_industrial_load(self):
         )
         assert dsm_profiles["p_min"].empty
 
-    @pytest.mark.local
     def test_get_profile_cts(self):
         edisgo = EDisGo(
             ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False
diff --git a/tests/io/test_electromobility_import.py b/tests/io/test_electromobility_import.py
index 0c35c719..f4c67eb3 100644
--- a/tests/io/test_electromobility_import.py
+++ b/tests/io/test_electromobility_import.py
@@ -191,7 +191,6 @@ def test_integrate_charging_parks(self):
 
         assert edisgo_ids_cp == edisgo_ids_topology
 
-    @pytest.mark.local
     def test_simbev_config_from_oedb(self):
         config_df = electromobility_import.simbev_config_from_oedb(
             engine=pytest.engine, scenario="eGon2035"
@@ -201,7 +200,6 @@ def test_simbev_config_from_oedb(self):
         assert config_df["stepsize"][0] == 15
         assert config_df["days"][0] == 365
 
-    @pytest.mark.local
     def test_potential_charging_parks_from_oedb(self):
         edisgo_obj = EDisGo(
             ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False
@@ -215,7 +213,6 @@ def test_potential_charging_parks_from_oedb(self):
         assert all(potential_parks_df.geom.iloc[10].within(grid_gdf.geometry))
         assert all(potential_parks_df.geom.iloc[100].within(grid_gdf.geometry))
 
-    @pytest.mark.local
     def test_charging_processes_from_oedb(self):
         edisgo_obj = EDisGo(
             ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False
diff --git a/tests/io/test_generators_import.py b/tests/io/test_generators_import.py
index 51ee4b5e..47765f70 100644
--- a/tests/io/test_generators_import.py
+++ b/tests/io/test_generators_import.py
@@ -484,7 +484,6 @@ class TestGeneratorsImportOEDB:
     """
 
     @pytest.mark.slow
-    @pytest.mark.oedbtest
     def test_oedb_legacy_without_timeseries(self):
         edisgo = EDisGo(
             ding0_grid=pytest.ding0_test_network_2_path,
@@ -498,7 +497,6 @@ def test_oedb_legacy_without_timeseries(self):
         assert np.isclose(edisgo.topology.generators_df.p_nom.sum(), 20.18783)
 
     @pytest.mark.slow
-    @pytest.mark.oedbtest
     def test_oedb_legacy_with_worst_case_timeseries(self):
         edisgo = EDisGo(ding0_grid=pytest.ding0_test_network_2_path)
         edisgo.set_time_series_worst_case_analysis()
@@ -570,7 +568,6 @@ def test_oedb_legacy_with_worst_case_timeseries(self):
         #     :, new_solar_gen.name] / new_solar_gen.p_nom).all()
 
     @pytest.mark.slow
-    @pytest.mark.oedbtest
     def test_oedb_legacy_with_timeseries_by_technology(self):
         timeindex = pd.date_range("1/1/2012", periods=3, freq="H")
         ts_gen_dispatchable = pd.DataFrame(
@@ -650,7 +647,6 @@ def test_oedb_legacy_with_timeseries_by_technology(self):
         #     :, new_solar_gen.name] / new_solar_gen.p_nom).all()
 
     @pytest.mark.slow
-    @pytest.mark.oedbtest
     def test_target_capacity(self):
         edisgo = EDisGo(
             ding0_grid=pytest.ding0_test_network_2_path,
@@ -710,7 +706,6 @@ def test_target_capacity(self):
             p_biomass_before * 1.0,
         )
 
-    @pytest.mark.local
     def test_oedb(self):
         edisgo = EDisGo(
             ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False
diff --git a/tests/io/test_heat_pump_import.py b/tests/io/test_heat_pump_import.py
index 12a327b4..5748afbe 100644
--- a/tests/io/test_heat_pump_import.py
+++ b/tests/io/test_heat_pump_import.py
@@ -57,7 +57,7 @@ def setup_resistive_heater_data_dh(self):
         )
         return hp_df
 
-    @pytest.mark.local
+    @pytest.mark.oedbtest
     def test_oedb(self, caplog):
         with caplog.at_level(logging.DEBUG):
             heat_pump_import.oedb(
@@ -196,7 +196,6 @@ def test__grid_integration(self, caplog):
         bus_rh = hp_df[hp_df.p_set == 0.17].bus[0]
         assert determine_bus_voltage_level(self.edisgo, bus_rh) == 6
 
-    @pytest.mark.local
     def test_efficiency_resistive_heaters_oedb(self):
         eta_dict = heat_pump_import.efficiency_resistive_heaters_oedb(
             scenario="eGon2035", engine=pytest.engine
diff --git a/tests/io/test_storage_import.py b/tests/io/test_storage_import.py
index 010fc02c..941cdc62 100644
--- a/tests/io/test_storage_import.py
+++ b/tests/io/test_storage_import.py
@@ -26,7 +26,6 @@ def setup_home_batteries_data(self):
         )
         return df
 
-    @pytest.mark.local
     def test_oedb(self, caplog):
         # test without new PV rooftop plants
         with caplog.at_level(logging.DEBUG):
diff --git a/tests/io/test_timeseries_import.py b/tests/io/test_timeseries_import.py
index c6abb872..ca0cef72 100644
--- a/tests/io/test_timeseries_import.py
+++ b/tests/io/test_timeseries_import.py
@@ -59,7 +59,6 @@ def test__timeindex_helper_func(self):
         assert_index_equal(ind, given_index)
         assert_index_equal(ind_full, timeindex)
 
-    @pytest.mark.oedbtest
     def test_feedin_oedb_legacy(self):
         edisgo = EDisGo(ding0_grid=pytest.ding0_test_network_path)
         timeindex = pd.date_range("1/1/2010", periods=3000, freq="H")
@@ -73,7 +72,6 @@ def test_feedin_oedb_legacy(self):
         assert np.isclose(feedin["solar"][1122075][timeindex[61]], 0.423823)
         assert np.isclose(feedin["wind"][1122075][timeindex[1356]], 0.106361)
 
-    @pytest.mark.local
     def test_feedin_oedb(self):
         edisgo_object = EDisGo(
             ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False
@@ -104,7 +102,6 @@ def test_load_time_series_demandlib(self):
         assert np.isclose(load.sum()["agricultural"], 1.0)
         assert np.isclose(load.sum()["industrial"], 1.0)
 
-    @pytest.mark.local
     def test_cop_oedb(self):
         edisgo = EDisGo(ding0_grid=pytest.ding0_test_network_path)
         cop_df = timeseries_import.cop_oedb(
@@ -140,7 +137,6 @@ def setup_egon_heat_pump_data(self):
         )
         return hp_df
 
-    @pytest.mark.local
     def test_heat_demand_oedb(self, caplog):
         edisgo_object = EDisGo(
             ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False
@@ -169,7 +165,6 @@ def test_heat_demand_oedb(self, caplog):
 
         # ToDo add further tests
 
-    @pytest.mark.local
     def test_electricity_demand_oedb(self, caplog):
         # test with one load each and without year
         edisgo_object = EDisGo(
@@ -216,7 +211,6 @@ def test_electricity_demand_oedb(self, caplog):
 
         # ToDo add further tests to check values
 
-    @pytest.mark.local
     def test_get_residential_heat_profiles_per_building(self):
         df = timeseries_import.get_residential_heat_profiles_per_building(
             [442081, 430859], "eGon2035", pytest.engine
@@ -224,7 +218,6 @@ def test_get_residential_heat_profiles_per_building(self):
         assert df.shape == (8760, 2)
         # ToDo add further tests
 
-    @pytest.mark.local
     def test_get_district_heating_heat_demand_profiles(self):
         df = timeseries_import.get_district_heating_heat_demand_profiles(
             [6], "eGon2035", pytest.engine
@@ -232,7 +225,6 @@ def test_get_district_heating_heat_demand_profiles(self):
         assert df.shape == (8760, 1)
         # ToDo add further tests
 
-    @pytest.mark.local
     def test_get_cts_profiles_per_building(self):
         edisgo_object = EDisGo(
             ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False
@@ -253,7 +245,6 @@ def test_get_cts_profiles_per_building(self):
         assert df.shape == (8760, len(cts_loads))
         # ToDo add further tests
 
-    @pytest.mark.local
     def test_get_cts_profiles_per_grid(self):
         df = timeseries_import.get_cts_profiles_per_grid(
             33535, "eGon2035", "heat", pytest.engine
@@ -265,7 +256,6 @@ def test_get_cts_profiles_per_grid(self):
         assert df.shape == (8760, 85)
         # ToDo add further tests
 
-    @pytest.mark.local
     def test_get_residential_electricity_profiles_per_building(self):
         df = timeseries_import.get_residential_electricity_profiles_per_building(
             [-1, 442081], "eGon2035", pytest.engine
@@ -280,7 +270,6 @@ def test_get_residential_electricity_profiles_per_building(self):
         assert df.shape == (8760, 1)
         assert np.isclose(df.loc[:, 442081].sum(), 4.288845, atol=1e-3)
 
-    @pytest.mark.local
     def test_get_industrial_electricity_profiles_per_site(self):
         # test with one site and one OSM area
         df = timeseries_import.get_industrial_electricity_profiles_per_site(
diff --git a/tests/network/test_heat.py b/tests/network/test_heat.py
index c1a59ae8..6ed384be 100644
--- a/tests/network/test_heat.py
+++ b/tests/network/test_heat.py
@@ -101,7 +101,6 @@ def test_set_cop(self):
             check_freq=False,
         )
 
-    @pytest.mark.local
     def test_set_cop_oedb(self, caplog):
         # ################### test with oedb ###################
         edisgo_object = EDisGo(
@@ -209,7 +208,6 @@ def test_set_heat_demand(self):
             check_freq=False,
         )
 
-    @pytest.mark.local
     def test_set_heat_demand_oedb(self):
         # test with oedb
         edisgo_object = EDisGo(
diff --git a/tests/network/test_timeseries.py b/tests/network/test_timeseries.py
index 2e8b717b..76807a7f 100644
--- a/tests/network/test_timeseries.py
+++ b/tests/network/test_timeseries.py
@@ -1235,7 +1235,6 @@ def test_worst_case_storage_units(self):
             )
 
     @pytest.mark.slow
-    @pytest.mark.oedbtest
     def test_predefined_fluctuating_generators_by_technology(self):
         timeindex = pd.date_range("1/1/2011 12:00", periods=2, freq="H")
         self.edisgo.timeseries.timeindex = timeindex
@@ -1404,7 +1403,6 @@ def test_predefined_fluctuating_generators_by_technology(self):
         )
         # fmt: on
 
-    @pytest.mark.local
     def test_predefined_fluctuating_generators_by_technology_oedb(self):
         edisgo_object = EDisGo(
             ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False
diff --git a/tests/test_edisgo.py b/tests/test_edisgo.py
index dbfa03a3..a7411e68 100755
--- a/tests/test_edisgo.py
+++ b/tests/test_edisgo.py
@@ -257,7 +257,6 @@ def test_set_time_series_active_power_predefined(self, caplog):
         assert self.edisgo.timeseries.storage_units_active_power.shape == (2, 0)
         assert self.edisgo.timeseries.storage_units_reactive_power.shape == (2, 0)
 
-    @pytest.mark.local
     def test_set_time_series_active_power_predefined_oedb(self):
         # test conventional_loads_ts="oedb" for all loads in grid
         edisgo_object = EDisGo(
@@ -382,7 +381,6 @@ def test_to_graph(self):
         )
 
     @pytest.mark.slow
-    @pytest.mark.oedbtest
     def test_generator_import(self):
         edisgo = EDisGo(ding0_grid=pytest.ding0_test_network_2_path)
         edisgo.import_generators("nep2035")
@@ -1296,7 +1294,6 @@ def test_import_electromobility(self):
         )
         # fmt: on
 
-    @pytest.mark.local
     def test_import_electromobility_oedb(self):
         """
         Test import from oedb.
@@ -1354,7 +1351,7 @@ def test_import_electromobility_oedb(self):
         )
         # fmt: on
 
-    @pytest.mark.local
+    @pytest.mark.oedbtest
     def test_import_heat_pumps(self):
         edisgo_object = EDisGo(
             ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False
diff --git a/tests/test_examples.py b/tests/test_examples.py
index 9f0a862e..8e31d88d 100644
--- a/tests/test_examples.py
+++ b/tests/test_examples.py
@@ -26,7 +26,6 @@ def test_plot_example_ipynb(self):
         assert result.exec_error is None
 
     @pytest.mark.slow
-    @pytest.mark.oedbtest
     def test_electromobility_example_ipynb(self):
         path = os.path.join(self.examples_dir_path, "electromobility_example.ipynb")
         notebook = pytest_notebook.notebook.load_notebook(path=path)
@@ -40,7 +39,6 @@ def test_electromobility_example_ipynb(self):
         assert result.exec_error is None
 
     @pytest.mark.slow
-    @pytest.mark.oedbtest
     def test_edisgo_simple_example_ipynb(self):
         path = os.path.join(self.examples_dir_path, "edisgo_simple_example.ipynb")
         notebook = pytest_notebook.notebook.load_notebook(path=path)
diff --git a/tests/tools/test_tools.py b/tests/tools/test_tools.py
index 66216ca6..f6d08f72 100644
--- a/tests/tools/test_tools.py
+++ b/tests/tools/test_tools.py
@@ -431,7 +431,6 @@ def test_determine_bus_voltage_level(self):
         assert tools.determine_bus_voltage_level(self.edisgo, bus_voltage_level_6) == 6
         assert tools.determine_bus_voltage_level(self.edisgo, bus_voltage_level_7) == 7
 
-    @pytest.mark.oedbtest
     def test_get_weather_cells_intersecting_with_grid_district(self):
         weather_cells = tools.get_weather_cells_intersecting_with_grid_district(
             self.edisgo
@@ -445,7 +444,6 @@ def test_get_weather_cells_intersecting_with_grid_district(self):
         # for some reason..
         assert 1122074 in weather_cells
 
-    @pytest.mark.local
     def test_get_weather_cells_intersecting_with_grid_district_egon(self):
         edisgo_obj = EDisGo(
             ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False