Repository: ieeh-tu-dresden/powerfactory-tools

Issue:
feat: multi PowerFactory version support
1. overhaul of the PowerFactory type registry:
    1. define data models of multiple PF versions
    2. verify the models
    3. `interface` chooses the correct type registry based on chosen PF version
2. implement a PF installations detection 
    1. show the user which ones are compatible with the used python version 
    2. let the user choose a PF installation.

Discussion:
SebastianDD: Each main version of PowerFactory is assigned to version-specific files.`./versions/pf20xx/...`
This partly leads to doubling of code, but ensures a readable and easy understandable code basis.

Patch:
diff --git a/README.md b/README.md
index 15a4012..52957c7 100644
--- a/README.md
+++ b/README.md
@@ -5,14 +5,15 @@
 A toolbox for Python based control of DIgSILENT PowerFactory.
 
 - [IEEH PowerFactory Tools](#ieeh-powerfactory-tools)
-  - [Field of Application](#-field-of-application)
-  - [Tutorials](#-tutorials)
-  - [General Remarks](#-general-remarks)
-  - [Installation](#-installation)
-  - [Compatibility](#-compatibility)
-  - [Development](#-development)
-  - [Acknowledgement](#-acknowledgement)
-  - [Attribution](#-attribution)
+  - [Field of Application](#application)
+  - [PowerFactory Interface](#interface)
+  - [General Remarks on Export](#remarks)
+  - [Tutorials](#tutorials)
+  - [Installation](#installation)
+  - [Compatibility](#compatibility)
+  - [Development](#development)
+  - [Acknowledgement](#acknowledgement)
+  - [Attribution](#attribution)
 
 ## <div id="application" /> Field of Application
 
@@ -21,27 +22,29 @@ Therefore, the Python-PowerFactory-API, provided by the company, is utilized.
 
 The following functionalities are provided:
 
-- export of calculation relevant grid data from a PowerFactory project to the [IEEH Power System Data Model](https://github.com/ieeh-tu-dresden/power-system-data-model)
-- basic control of PowerFactory
-- [intended in future release] import from external grid data into the PowerFactory environment
+- **Interface**: collection of comfort functions for the work with the PowerFactory API
+- **Exporter**: export of calculation relevant grid data from a PowerFactory project to the [IEEH Power System Data Model (PSDM)](https://github.com/ieeh-tu-dresden/power-system-data-model)
+- **Importer**: import from external grid data into the PowerFactory environment [intended in future release]
 
-## <div id="tutorials" /> Tutorials
+**Important**: As the set of different elements, data types and attributes can differ between the various main versions (e.g. `2022`) of PowerFactory, all functionalities are set up individual for main versions.
 
-Please consider the [README](./examples/README.md) in the example section. Here, Jupyter notebooks are provided to get in touch with the usage of this toolbox:
 
-- for export: [powerfactory_export.ipynb](./examples/powerfactory_export.ipynb)
-- for control: [powerfactory_control.ipynb](./examples/powerfactory_control.ipynb)
+## <div id="interface" /> PowerFactory Interface
+The toolbox builds up on the [PowerFactoryInterface](./powerfactory_tools/versions/pf2022/interface.py), that provides comfort functions to:
+- connect to PowerFactory
+- create and alter PowerFactory elements ("physical" elements, "organizational" elements, commands, etc.)
+- collect PowerFactory elements of specific types
+- execute PowerFactory commands
+- ...
 
-In addition, please see this interactive example [![Code Ocean Capsule](https://codeocean.com/codeocean-assets/badge/open-in-code-ocean.svg)](https://codeocean.com/capsule/4423034/tree/v1) how to import a PSDM grid representation in `Matlab` for grid calculation purposes.
+## <div id="remarks" /> General Remarks
 
-
-## <div id="remarks" /> General Remarks on Export
-
-Please find below some important general remarks and assumptions to consider for the application:
+Please find below some important general remarks and assumptions to consider for the application.
 
 ### General
 
-After successful connection to PowerFactory via [PowerFactoryInterface](./powerfactory_tools/interface.py), a **temporary unit conversion to default values is automatically performed** to have a project setting independent behavior. The units are reset when the interface is closed.
+A connection to PowerFactory is established via [PowerFactoryInterface](./powerfactory_tools/versions/pf2022/interface.py).
+After this initialization, a **temporary unit conversion to default values is automatically performed** to have a project setting independent behavior. The units are reset when the interface is closed.
 During an active connection, the following units apply:
 
 - power in MW
@@ -51,7 +54,9 @@ During an active connection, the following units apply:
 
 ### Exporter
 
-- The grid export follows the rules of usage recommended by [psdm](https://github.com/ieeh-tu-dresden/power-system-data-model#-general-remarks):
+The [PowerFactoryExporter](./powerfactory_tools/versions/pf2022/exporter/exporter.py) connects to PowerFactory via [PowerFactoryInterface](./powerfactory_tools/versions/pf2022/interface.py).
+
+- The grid export follows the rules of usage recommended by [PSDM](https://github.com/ieeh-tu-dresden/power-system-data-model#-general-remarks):
   - The passive sign convention is used for all types of loads (consumer as well as producer).
   - The `Rated Power` is always defined positive (absolute value).
 - By default, all assests of all active grids within the selected study case are to be exported, see [example readme](./examples/README.md).
@@ -77,25 +82,34 @@ During an active connection, the following units apply:
   - The default load model of medium-voltage loads (`ElmLodmv`) is of type `const. power`.
   - The default load model of low-voltage loads (`ElmLodlv`, `ElmLodlvp`) is of type `const. current`.
   - Be aware that the reference voltage of the load model must not match the nominal voltage of the terminal the load is connected to.
-  - By default, the power factor direction of the rated power is set to "not defined", see docs at [LoadPower - as_rated_power()](./powerfactory_tools/exporter/load_power.py).
+  - By default, the power factor direction of the rated power is set to "not defined", see docs at [LoadPower - as_rated_power()](./powerfactory_tools/versions/pf2022/exporter/load_power.py).
   - Connected consumer loads with an active and reactive power of zero leads to a RatedPower of `NaN`. Consider to exclude them for export.
 
 - Remarks on export of `transformer`:
   - The impedances of all winding objects are referred to the high voltage side of the transformer.
   - The impedance of transformer earthing is an absolute natural value.
   - The zero sequence impedances are exported without considering the vector group, resulting zero sequence must be calculated separately by the user afterwards.
-  - The zero sequence magnetising impedances are dependent on the wiring group, see docs at [PowerFactoryExporter - create_transformer_2w()](./powerfactory_tools/exporter/exporter.py).
+  - The zero sequence magnetising impedances are dependent on the wiring group, see docs at [PowerFactoryExporter - create_transformer_2w()](./powerfactory_tools/versions/pf2022/exporter/exporter.py).
 
 - Remarks on export of `fuses`:
   - Branch like fuses are exported as switching state.
   - Element fuses does not apply a switching state by their own in PowerFactory but considered in export as applicable switching state.
 
 - Remarks on export of the `SteadyStateCase`:
-  - The operating points of the loads are specified by the controller and the associated load model in the topology for active or reactive power, see docs at [Power System Data Model](https://github.com/ieeh-tu-dresden/power-system-data-model?tab=readme-ov-file#-general-remarks).
+  - The operating points of the loads are specified by the controller and the associated load model in the topology for active or reactive power, see docs at [PSDM](https://github.com/ieeh-tu-dresden/power-system-data-model?tab=readme-ov-file#-general-remarks).
   - By default a consumer load has a Q-controller of type `CosPhiConst`, except in the case where active and reactive power are explicitly specified in the load flow mask in PowerFactory, then it's `QConst`.
   - It is assumed, that a station controller (if relevant) is exclusively assigned to a single generator.
   The generator itself ought to be parameterized in the same way as the station controller to ensure that the exported operating point of *Q* is the same that set by the station controller.
 
+## <div id="tutorials" /> Tutorials
+
+Please consider the [README](./examples/README.md) in the example section. Here, Jupyter notebooks are provided to get in touch with the usage of this toolbox:
+
+- for export: [powerfactory_export.ipynb](./examples/powerfactory_export.ipynb)
+- for control: [powerfactory_control.ipynb](./examples/powerfactory_control.ipynb)
+
+In addition, please see this interactive example [![Code Ocean Capsule](https://codeocean.com/codeocean-assets/badge/open-in-code-ocean.svg)](https://codeocean.com/capsule/4423034/tree/v1) how to import a PSDM grid representation in `Matlab` for grid calculation purposes.
+
 ## <div id="installation" /> Installation
 
 Install via pip:
diff --git a/examples/README.md b/examples/README.md
index 917ae25..fdf8014 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -6,7 +6,9 @@ Examples for application of powerfactory exporter and controller.
   - [Export Functionalities](#export-functionalities)
   - [Control Functionalities](#control-functionalities)
   - [Raw PSDM Import](#import-functionalities)
-  - [PowerFactory Example Project](#-powerfactory-example-project)
+  - [PowerFactory Example Project](#powerfactory-example-project)
+
+The whole examples are based on the PowerFactory version `2022`!
 
 ## <div id="export-functionalities" /> Export Functionalities
 
@@ -26,12 +28,12 @@ to three different json files using the [power system data model (psdm)][link_to
 
 ### Usage
 
-**Please note** that default values for the installation directory and version number of PowerFactory are used.
-The user can adapt `powerfactory_path` and `powerfactory_version` when initializing the [PowerFactoryInterface][link_to_interface].
+**Please note**, that default values for the PowerFactory installation path and the Python version are used.
+If necessary, one can adapt `powerfactory_path`, `powerfactory_service_pack` and `python_version` when initializing the [PowerFactoryExporter][link_to_exporter].
 
 By default, **all assests of all active grids** within the selected PowerFactory project are to be exported.
-- The preferred way for export is to first define study cases in PowerFactory und then assign the desired study cases to the `export()` function call, see [export example](powerfactory_export.ipynb).
-- For more control, the user can select _study cases_, _operation scenarios_ and _grid variations_ before export, see [control example 7-9](powerfactory_control.ipynb).
+- The preferred way for export is to assign the desired study cases to the `export()` function call, see [export example](powerfactory_export.ipynb).
+- Alternatively, one can select _study cases_, _operation scenarios_ and _grid variations_ before export for more control, see [control example 7-9](powerfactory_control.ipynb).
 
 The following figure provides a short overview of the dependencies within a PowerFactory project.
 
@@ -54,11 +56,11 @@ The example includes:
 
 ## <div id="import-functionalities" /> Raw PSDM Import
 
-The jupyter notebook [powerfactory_import.ipynb](powerfactory_import.ipynb) is provided to how to apply a raw import of a given (exported) PSDM grid representation.
+The jupyter notebook [powerfactory_import.ipynb](powerfactory_import.ipynb) is provided to see how to apply a raw import of a given (exported) PSDM grid representation.
 
 Here, `PSDM class objects` are generated out of a given `json`-file.
 
-## <div id="example project" /> PowerFactory Example Project
+## <div id="powerfactory-example-project" /> PowerFactory Example Project
 The related PowerFactory example project `PF2022_PowerFactory-Tools.pfd` is provided in [grids][link_to_example_grids]. 
 The project contains:
 - 3-bus high voltage grid
@@ -122,5 +124,5 @@ This grid is an extension to the 'HV_9_Bus' grid and contains:
 ![MV_2_Bus grid](./grids/MV_2_Bus.png)
 
 [link_to_example_grids]: ./grids
-[link_to_interface]: ../powerfactory_tools/interface.py
+[link_to_exporter]: ../powerfactory_tools/versions/pf2022/exporter/exporter.py
 [link_to_psdm]: https://github.com/ieeh-tu-dresden/power-system-data-model
diff --git a/examples/powerfactory_control.ipynb b/examples/powerfactory_control.ipynb
index 5c04c73..f8bcdf2 100644
--- a/examples/powerfactory_control.ipynb
+++ b/examples/powerfactory_control.ipynb
@@ -24,18 +24,27 @@
    "metadata": {},
    "outputs": [],
    "source": [
+    "import datetime as dt\n",
     "import logging\n",
-    "import loguru\n",
     "import pathlib\n",
     "import sys\n",
-    "import datetime as dt\n",
     "\n",
-    "from powerfactory_tools import PowerFactoryInterface\n",
-    "from powerfactory_tools.powerfactory_types import CalculationType\n",
-    "from powerfactory_tools.powerfactory_types import ModeInpLoad\n",
-    "from powerfactory_tools.powerfactory_types import PFClassId\n",
-    "from powerfactory_tools.powerfactory_types import ResultExportMode\n",
-    "from powerfactory_tools.utils.io import FileType"
+    "import loguru\n",
+    "\n",
+    "from powerfactory_tools.utils.io import FileType\n",
+    "from powerfactory_tools.versions.pf2022.types import CalculationType\n",
+    "from powerfactory_tools.versions.pf2022.types import PFClassId\n",
+    "from powerfactory_tools.versions.pf2022.types import ModeInpLoad\n",
+    "from powerfactory_tools.versions.pf2022.types import ResultExportMode"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Select an Interface that is compatible to your PowerFactory version  \n",
+    "- Specify additional PowerFactory configuration\n",
+    "- Name the PowerFactory project"
    ]
   },
   {
@@ -44,12 +53,17 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "# Consider to use raw strings to avoid misinterpretation of special characters, e.g. r\"dir\\New Project\" or r\"dir\\1-HV-grid\".\n",
-    "PROJECT_NAME = \"PowerFactory-Tools\"  # may be also full path \"dir_name\\project_name\"\n",
-    "EXPORT_PATH = pathlib.Path(\"control_action_results\")\n",
+    "# Import the PowerFactoryInterface that is compatible with PowerFactory in version 2022\n",
+    "from powerfactory_tools.versions.pf2022 import PowerFactoryInterface\n",
+    "\n",
+    "# PowerFactory configuration\n",
+    "PF_SERVICE_PACK = 2  # mandatory\n",
     "PF_USER_PROFILE = \"\"  # specification may be necessary\n",
     "PF_INI_NAME = \"\"  # optional specification of ini file name to switch to full version (e.g. PowerFactoryFull for file PowerFactoryFull.ini)\n",
-    "PYTHON_VERSION = \"3.10\""
+    "\n",
+    "# Consider to use raw strings to avoid misinterpretation of special characters, e.g. r\"dir\\New Project\" or r\"dir\\1-HV-grid\".\n",
+    "PROJECT_NAME = \"PowerFactory-Tools-Dev\"  # may be also full path \"dir_name\\project_name\"\n",
+    "EXPORT_PATH = pathlib.Path(\"control_action_results\")"
    ]
   },
   {
@@ -472,10 +486,10 @@
     "\n",
     "\n",
     "with PowerFactoryInterface(\n",
-    "    project_name=PROJECT_NAME,\n",
+    "    powerfactory_service_pack=PF_SERVICE_PACK,\n",
     "    powerfactory_user_profile=PF_USER_PROFILE,\n",
     "    powerfactory_ini_name=PF_INI_NAME,\n",
-    "    python_version=PYTHON_VERSION,\n",
+    "    project_name=PROJECT_NAME,\n",
     "    logging_level=logging.INFO,\n",
     "    # log_file_path=full_export_path / pathlib.Path(\"pf_control.log\"),  # noqa: ERA001\n",
     ") as pfi:\n",
@@ -506,8 +520,9 @@
    "source": [
     "import multiprocessing\n",
     "\n",
-    "POWERFACTORY_PATH = pathlib.Path(\"C:/Program Files/DIgSILENT\")\n",
-    "POWERFACTORY_VERSION = \"2022 SP2\"\n",
+    "from powerfactory_tools.versions.pf2022.interface import DEFAULT_POWERFACTORY_PATH\n",
+    "from powerfactory_tools.versions.pf2022.interface import DEFAULT_PYTHON_VERSION\n",
+    "from powerfactory_tools.versions.pf2022.interface import ValidPythonVersion\n",
     "\n",
     "\n",
     "# Define a controller process\n",
@@ -515,22 +530,20 @@
     "    def __init__(\n",
     "        self,\n",
     "        *,\n",
-    "        export_path: pathlib.Path,\n",
     "        project_name: str,\n",
+    "        powerfactory_path: pathlib.Path = DEFAULT_POWERFACTORY_PATH,\n",
+    "        powerfactory_service_pack: int = \"\",\n",
     "        powerfactory_user_profile: str = \"\",\n",
-    "        powerfactory_path: pathlib.Path = POWERFACTORY_PATH,\n",
-    "        powerfactory_version: str = POWERFACTORY_VERSION,\n",
     "        powerfactory_ini_name: str = \"\",\n",
-    "        python_version: str = PYTHON_VERSION,\n",
+    "        python_version: ValidPythonVersion = DEFAULT_PYTHON_VERSION,\n",
     "        logging_level: int = logging.INFO,\n",
     "        log_file_path: pathlib.Path | None = None,\n",
     "    ) -> None:\n",
     "        super().__init__()\n",
-    "        self.export_path = export_path\n",
     "        self.project_name = project_name\n",
-    "        self.powerfactory_user_profile = powerfactory_user_profile\n",
     "        self.powerfactory_path = powerfactory_path\n",
-    "        self.powerfactory_version = powerfactory_version\n",
+    "        self.powerfactory_service_pack = powerfactory_service_pack\n",
+    "        self.powerfactory_user_profile = powerfactory_user_profile\n",
     "        self.powerfactory_ini_name = powerfactory_ini_name\n",
     "        self.python_version = python_version\n",
     "        self.logging_level = logging_level\n",
@@ -539,9 +552,8 @@
     "    def run(self) -> None:\n",
     "        pfi = PowerFactoryInterface(\n",
     "            project_name=self.project_name,\n",
+    "            powerfactory_service_pack=self.powerfactory_service_pack,\n",
     "            powerfactory_user_profile=self.powerfactory_user_profile,\n",
-    "            powerfactory_path=self.powerfactory_path,\n",
-    "            powerfactory_version=self.powerfactory_version,\n",
     "            powerfactory_ini_name=self.powerfactory_ini_name,\n",
     "            python_version=self.python_version,\n",
     "            logging_level=self.logging_level,\n",
@@ -571,10 +583,12 @@
     "\n",
     "# Initialize controller process\n",
     "process = PowerFactoryControllerProcess(\n",
-    "    project_name=PROJECT_NAME,\n",
-    "    export_path=full_export_path,\n",
+    "    powerfactory_service_pack=PF_SERVICE_PACK,\n",
     "    powerfactory_user_profile=PF_USER_PROFILE,\n",
     "    powerfactory_ini_name=PF_INI_NAME,\n",
+    "    python_version=DEFAULT_PYTHON_VERSION,\n",
+    "    project_name=PROJECT_NAME,\n",
+    "    export_path=full_export_path,\n",
     "    logging_level=logging.DEBUG,\n",
     "    log_file_path=full_export_path / pathlib.Path(\"pf_control.log\"),\n",
     ")\n",
diff --git a/examples/powerfactory_export.ipynb b/examples/powerfactory_export.ipynb
index 448a45e..29f7de9 100644
--- a/examples/powerfactory_export.ipynb
+++ b/examples/powerfactory_export.ipynb
@@ -28,25 +28,37 @@
     "import logging\n",
     "import pathlib\n",
     "\n",
-    "from powerfactory_tools.exporter import PowerFactoryExporter\n",
-    "from powerfactory_tools.exporter import export_powerfactory_data\n",
     "from psdm.steadystate_case.case import Case as SteadystateCase\n",
     "from psdm.topology.topology import Topology\n",
     "from psdm.topology_case.case import Case as TopologyCase"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Select an Interface that is compatible to your PowerFactory version  \n",
+    "- Specify additional PowerFactory configuration\n",
+    "- Name the PowerFactory project"
+   ]
+  },
   {
    "cell_type": "code",
    "execution_count": null,
    "metadata": {},
    "outputs": [],
    "source": [
+    "# Import the PowerFactoryExporter that is compatible with PowerFactory in version 2022\n",
+    "from powerfactory_tools.versions.pf2022 import PowerFactoryExporter\n",
+    "\n",
+    "# PowerFactory configuration\n",
+    "PF_SERVICE_PACK = 2  # mandatory\n",
+    "PF_USER_PROFILE = \"\"  # specification may be necessary\n",
+    "\n",
     "# Consider to use raw strings to avoid misinterpretation of special characters, e.g. r\"dir\\New Project\" or r\"dir\\1-HV-grid\".\n",
     "PROJECT_NAME = \"PowerFactory-Tools\"  # may be also full path \"dir_name\\project_name\"\n",
-    "EXPORT_PATH = pathlib.Path(\"export\")\n",
-    "PF_USER_PROFILE = \"\"  # specification may be necessary\n",
-    "PYTHON_VERSION = \"3.10\"\n",
-    "STUDY_CASES = [\"Base\", \"Outage\", \"Industry_Park\"]"
+    "STUDY_CASES = [\"Base\", \"Outage\", \"Industry_Park\"]\n",
+    "EXPORT_PATH = pathlib.Path(\"export\")"
    ]
   },
   {
@@ -67,8 +79,8 @@
     "# Here, only active grids will be exported.\n",
     "with PowerFactoryExporter(\n",
     "    project_name=PROJECT_NAME,\n",
+    "    powerfactory_service_pack=PF_SERVICE_PACK,\n",
     "    powerfactory_user_profile=PF_USER_PROFILE,\n",
-    "    python_version=PYTHON_VERSION,\n",
     "    logging_level=logging.INFO,\n",
     ") as exporter:\n",
     "    _project_name = PROJECT_NAME.split(\"\\\\\")\n",
@@ -97,14 +109,16 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "ext_log_file_path = pathlib.Path(\"export\\logfile.txt\")\n",
+    "from powerfactory_tools.versions.pf2022 import export_powerfactory_data\n",
+    "\n",
+    "ext_log_file_path = pathlib.Path(r\"export\\logfile.txt\")\n",
     "# As the export function is executed in a process that is terminated after execution, the PowerFactory API is also closed.\n",
     "export_powerfactory_data(\n",
+    "    powerfactory_service_pack=PF_SERVICE_PACK,\n",
+    "    powerfactory_user_profile=PF_USER_PROFILE,\n",
     "    export_path=EXPORT_PATH,\n",
     "    project_name=PROJECT_NAME,\n",
     "    study_case_names=STUDY_CASES,\n",
-    "    powerfactory_user_profile=PF_USER_PROFILE,\n",
-    "    python_version=PYTHON_VERSION,\n",
     "    logging_level=logging.INFO,\n",
     "    log_file_path=ext_log_file_path,\n",
     ")"
diff --git a/powerfactory_tools/__init__.py b/powerfactory_tools/__init__.py
index ac17ef5..e69de29 100644
--- a/powerfactory_tools/__init__.py
+++ b/powerfactory_tools/__init__.py
@@ -1,9 +0,0 @@
-# :author: Sasan Jacob Rasti <sasan_jacob.rasti@tu-dresden.de>
-# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2023.
-# :license: BSD 3-Clause
-
-from powerfactory_tools.interface import PowerFactoryInterface
-
-__all__ = [
-    "PowerFactoryInterface",
-]
diff --git a/powerfactory_tools/__version__.py b/powerfactory_tools/__version__.py
new file mode 100644
index 0000000..feeaa3f
--- /dev/null
+++ b/powerfactory_tools/__version__.py
@@ -0,0 +1,6 @@
+# :author: Sasan Jacob Rasti <sasan_jacob.rasti@tu-dresden.de>
+# :author: Sebastian Krahmer <sebastian.krahmer@tu-dresden.de>
+# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2023.
+# :license: BSD 3-Clause
+
+VERSION = "2.1.0"
diff --git a/powerfactory_tools/exporter/__init__.py b/powerfactory_tools/exporter/__init__.py
deleted file mode 100644
index fe07f8b..0000000
--- a/powerfactory_tools/exporter/__init__.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# :author: Sasan Jacob Rasti <sasan_jacob.rasti@tu-dresden.de>
-# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2023.
-# :license: BSD 3-Clause
-
-from powerfactory_tools.exporter.exporter import PowerFactoryExporter
-from powerfactory_tools.exporter.exporter import export_powerfactory_data
-
-__all__ = [
-    "PowerFactoryExporter",
-    "export_powerfactory_data",
-]
diff --git a/powerfactory_tools/versions/pf2022/__init__.py b/powerfactory_tools/versions/pf2022/__init__.py
new file mode 100644
index 0000000..e467b8e
--- /dev/null
+++ b/powerfactory_tools/versions/pf2022/__init__.py
@@ -0,0 +1,13 @@
+# :author: Sasan Jacob Rasti <sasan_jacob.rasti@tu-dresden.de>
+# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2024.
+# :license: BSD 3-Clause
+
+from powerfactory_tools.versions.pf2022.exporter.exporter import PowerFactoryExporter
+from powerfactory_tools.versions.pf2022.exporter.exporter import export_powerfactory_data
+from powerfactory_tools.versions.pf2022.interface import PowerFactoryInterface
+
+__all__ = [
+    "PowerFactoryInterface",
+    "PowerFactoryExporter",
+    "export_powerfactory_data",
+]
diff --git a/powerfactory_tools/constants.py b/powerfactory_tools/versions/pf2022/constants.py
similarity index 90%
rename from powerfactory_tools/constants.py
rename to powerfactory_tools/versions/pf2022/constants.py
index 12a2787..35446ca 100644
--- a/powerfactory_tools/constants.py
+++ b/powerfactory_tools/versions/pf2022/constants.py
@@ -1,14 +1,14 @@
 # :author: Sasan Jacob Rasti <sasan_jacob.rasti@tu-dresden.de>
 # :author: Sebastian Krahmer <sebastian.krahmer@tu-dresden.de>
-# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2023.
+# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2024.
 # :license: BSD 3-Clause
 
 from __future__ import annotations
 
 import typing as t
 
-from powerfactory_tools.powerfactory_types import Currency
-from powerfactory_tools.powerfactory_types import MetricPrefix
+from powerfactory_tools.versions.pf2022.types import Currency
+from powerfactory_tools.versions.pf2022.types import MetricPrefix
 
 if t.TYPE_CHECKING:
     from collections.abc import Sequence
diff --git a/powerfactory_tools/versions/pf2022/data.py b/powerfactory_tools/versions/pf2022/data.py
new file mode 100644
index 0000000..0988179
--- /dev/null
+++ b/powerfactory_tools/versions/pf2022/data.py
@@ -0,0 +1,37 @@
+# :author: Sasan Jacob Rasti <sasan_jacob.rasti@tu-dresden.de>
+# :author: Sebastian Krahmer <sebastian.krahmer@tu-dresden.de>
+# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2024.
+# :license: BSD 3-Clause
+
+from __future__ import annotations
+
+import dataclasses
+import typing as t
+
+if t.TYPE_CHECKING:
+    import collections.abc as cabc
+    import datetime as dt
+
+    from powerfactory_tools.versions.pf2022.types import PowerFactoryTypes as PFTypes
+
+
+@dataclasses.dataclass
+class PowerFactoryData:
+    date: dt.date
+    project_name: str
+    grid_name: str
+    external_grids: cabc.Sequence[PFTypes.ExternalGrid]
+    terminals: cabc.Sequence[PFTypes.Terminal]
+    lines: cabc.Sequence[PFTypes.Line]
+    transformers_2w: cabc.Sequence[PFTypes.Transformer2W]
+    transformers_3w: cabc.Sequence[PFTypes.Transformer3W]
+    loads: cabc.Sequence[PFTypes.Load]
+    loads_lv: cabc.Sequence[PFTypes.LoadLV]
+    loads_mv: cabc.Sequence[PFTypes.LoadMV]
+    generators: cabc.Sequence[PFTypes.Generator]
+    pv_systems: cabc.Sequence[PFTypes.PVSystem]
+    couplers: cabc.Sequence[PFTypes.Coupler]
+    switches: cabc.Sequence[PFTypes.Switch]
+    bfuses: cabc.Sequence[PFTypes.BFuse]
+    efuses: cabc.Sequence[PFTypes.EFuse]
+    ac_current_sources: cabc.Sequence[PFTypes.AcCurrentSource]
diff --git a/powerfactory_tools/versions/pf2022/exporter/__init__.py b/powerfactory_tools/versions/pf2022/exporter/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/powerfactory_tools/exporter/exporter.py b/powerfactory_tools/versions/pf2022/exporter/exporter.py
similarity index 97%
rename from powerfactory_tools/exporter/exporter.py
rename to powerfactory_tools/versions/pf2022/exporter/exporter.py
index 8c9ba52..8e4a8cd 100644
--- a/powerfactory_tools/exporter/exporter.py
+++ b/powerfactory_tools/versions/pf2022/exporter/exporter.py
@@ -1,6 +1,6 @@
 # :author: Sasan Jacob Rasti <sasan_jacob.rasti@tu-dresden.de>
 # :author: Sebastian Krahmer <sebastian.krahmer@tu-dresden.de>
-# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2023.
+# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2024.
 # :license: BSD 3-Clause
 
 from __future__ import annotations
@@ -63,42 +63,42 @@ from psdm.topology.windings import Winding
 from psdm.topology_case.case import Case as TopologyCase
 from psdm.topology_case.element_state import ElementState
 
-from powerfactory_tools.constants import DEFAULT_PHASE_QUANTITY
-from powerfactory_tools.constants import DecimalDigits
-from powerfactory_tools.constants import Exponents
-from powerfactory_tools.exporter.load_power import ConsolidatedLoadPhaseConnectionType
-from powerfactory_tools.exporter.load_power import ControlTypeFactory
-from powerfactory_tools.exporter.load_power import LoadPower
-from powerfactory_tools.interface import VERSION
-from powerfactory_tools.interface import PowerFactoryData
-from powerfactory_tools.interface import PowerFactoryInterface
-from powerfactory_tools.powerfactory_types import CosPhiChar
-from powerfactory_tools.powerfactory_types import CtrlVoltageRef
-from powerfactory_tools.powerfactory_types import ExternalQCtrlMode
-from powerfactory_tools.powerfactory_types import GeneratorPhaseConnectionType
-from powerfactory_tools.powerfactory_types import GeneratorSystemType
-from powerfactory_tools.powerfactory_types import IOpt
-from powerfactory_tools.powerfactory_types import LoadLVPhaseConnectionType
-from powerfactory_tools.powerfactory_types import LoadPhaseConnectionType
-from powerfactory_tools.powerfactory_types import LocalQCtrlMode
-from powerfactory_tools.powerfactory_types import PFClassId
-from powerfactory_tools.powerfactory_types import Phase1PH as PFPhase1PH
-from powerfactory_tools.powerfactory_types import Phase2PH as PFPhase2PH
-from powerfactory_tools.powerfactory_types import Phase3PH as PFPhase3PH
-from powerfactory_tools.powerfactory_types import PowerFactoryTypes
-from powerfactory_tools.powerfactory_types import PowerFactoryTypes as PFTypes
-from powerfactory_tools.powerfactory_types import PowerModelType
-from powerfactory_tools.powerfactory_types import QChar
-from powerfactory_tools.powerfactory_types import TerminalPhaseConnectionType
-from powerfactory_tools.powerfactory_types import TerminalVoltageSystemType
-from powerfactory_tools.powerfactory_types import TrfNeutralConnectionType
-from powerfactory_tools.powerfactory_types import TrfNeutralPointState
-from powerfactory_tools.powerfactory_types import TrfPhaseTechnology
-from powerfactory_tools.powerfactory_types import TrfTapSide
-from powerfactory_tools.powerfactory_types import Vector
-from powerfactory_tools.powerfactory_types import VectorGroup
-from powerfactory_tools.powerfactory_types import VoltageSystemType as ElementVoltageSystemType
-from powerfactory_tools.quantities import QuantityConverter as Qc
+from powerfactory_tools.__version__ import VERSION
+from powerfactory_tools.versions.pf2022.constants import DEFAULT_PHASE_QUANTITY
+from powerfactory_tools.versions.pf2022.constants import DecimalDigits
+from powerfactory_tools.versions.pf2022.constants import Exponents
+from powerfactory_tools.versions.pf2022.exporter.load_power import ConsolidatedLoadPhaseConnectionType
+from powerfactory_tools.versions.pf2022.exporter.load_power import ControlTypeFactory
+from powerfactory_tools.versions.pf2022.exporter.load_power import LoadPower
+from powerfactory_tools.versions.pf2022.interface import DEFAULT_POWERFACTORY_PATH
+from powerfactory_tools.versions.pf2022.interface import DEFAULT_PYTHON_VERSION
+from powerfactory_tools.versions.pf2022.interface import PowerFactoryInterface
+from powerfactory_tools.versions.pf2022.interface import ValidPythonVersion
+from powerfactory_tools.versions.pf2022.quantities import QuantityConverter as Qc
+from powerfactory_tools.versions.pf2022.types import CosPhiChar
+from powerfactory_tools.versions.pf2022.types import CtrlVoltageRef
+from powerfactory_tools.versions.pf2022.types import ExternalQCtrlMode
+from powerfactory_tools.versions.pf2022.types import GeneratorPhaseConnectionType
+from powerfactory_tools.versions.pf2022.types import GeneratorSystemType
+from powerfactory_tools.versions.pf2022.types import IOpt
+from powerfactory_tools.versions.pf2022.types import LoadLVPhaseConnectionType
+from powerfactory_tools.versions.pf2022.types import LoadPhaseConnectionType
+from powerfactory_tools.versions.pf2022.types import LocalQCtrlMode
+from powerfactory_tools.versions.pf2022.types import PFClassId
+from powerfactory_tools.versions.pf2022.types import Phase1PH as PFPhase1PH
+from powerfactory_tools.versions.pf2022.types import Phase2PH as PFPhase2PH
+from powerfactory_tools.versions.pf2022.types import Phase3PH as PFPhase3PH
+from powerfactory_tools.versions.pf2022.types import PowerModelType
+from powerfactory_tools.versions.pf2022.types import QChar
+from powerfactory_tools.versions.pf2022.types import TerminalPhaseConnectionType
+from powerfactory_tools.versions.pf2022.types import TerminalVoltageSystemType
+from powerfactory_tools.versions.pf2022.types import TrfNeutralConnectionType
+from powerfactory_tools.versions.pf2022.types import TrfNeutralPointState
+from powerfactory_tools.versions.pf2022.types import TrfPhaseTechnology
+from powerfactory_tools.versions.pf2022.types import TrfTapSide
+from powerfactory_tools.versions.pf2022.types import Vector
+from powerfactory_tools.versions.pf2022.types import VectorGroup
+from powerfactory_tools.versions.pf2022.types import VoltageSystemType as ElementVoltageSystemType
 
 if t.TYPE_CHECKING:
     from collections.abc import Sequence
@@ -106,12 +106,11 @@ if t.TYPE_CHECKING:
 
     import typing_extensions as te
 
-    ElementBase = PFTypes.GeneratorBase | PFTypes.LoadBase3Ph | PFTypes.ExternalGrid
+    from powerfactory_tools.versions.pf2022.data import PowerFactoryData
+    from powerfactory_tools.versions.pf2022.types import PowerFactoryTypes as PFTypes
 
+    ElementBase = PFTypes.GeneratorBase | PFTypes.LoadBase3Ph | PFTypes.ExternalGrid
 
-POWERFACTORY_PATH = pathlib.Path("C:/Program Files/DIgSILENT")
-POWERFACTORY_VERSION = "2022 SP2"
-PYTHON_VERSION = "3.10"
 
 FULL_DYNAMIC = 100
 M_TAB2015_MIN_THRESHOLD = 0.01
@@ -143,9 +142,9 @@ class PowerFactoryExporterProcess(multiprocessing.Process):
         export_path: pathlib.Path,
         project_name: str,
         powerfactory_user_profile: str = "",
-        powerfactory_path: pathlib.Path = POWERFACTORY_PATH,
-        powerfactory_version: str = POWERFACTORY_VERSION,
-        python_version: str = PYTHON_VERSION,
+        powerfactory_path: pathlib.Path = DEFAULT_POWERFACTORY_PATH,
+        powerfactory_service_pack: int | None = None,
+        python_version: ValidPythonVersion = DEFAULT_PYTHON_VERSION,
         logging_level: int = logging.DEBUG,
         log_file_path: pathlib.Path | None = None,
         topology_name: str | None = None,
@@ -158,7 +157,7 @@ class PowerFactoryExporterProcess(multiprocessing.Process):
         self.project_name = project_name
         self.powerfactory_user_profile = powerfactory_user_profile
         self.powerfactory_path = powerfactory_path
-        self.powerfactory_version = powerfactory_version
+        self.powerfactory_service_pack = powerfactory_service_pack
         self.python_version = python_version
         self.logging_level = logging_level
         self.log_file_path = log_file_path
@@ -172,8 +171,6 @@ class PowerFactoryExporterProcess(multiprocessing.Process):
             project_name=self.project_name,
             powerfactory_user_profile=self.powerfactory_user_profile,
             powerfactory_path=self.powerfactory_path,
-            powerfactory_version=self.powerfactory_version,
-            python_version=self.python_version,
             logging_level=self.logging_level,
             log_file_path=self.log_file_path,
         )
@@ -190,9 +187,9 @@ class PowerFactoryExporterProcess(multiprocessing.Process):
 class PowerFactoryExporter:
     project_name: str
     powerfactory_user_profile: str = ""
-    powerfactory_path: pathlib.Path = POWERFACTORY_PATH
-    powerfactory_version: str = POWERFACTORY_VERSION
-    python_version: str = PYTHON_VERSION
+    powerfactory_path: pathlib.Path = DEFAULT_POWERFACTORY_PATH
+    powerfactory_service_pack: int | None = None
+    python_version: ValidPythonVersion = DEFAULT_PYTHON_VERSION
     logging_level: int = logging.DEBUG
     log_file_path: pathlib.Path | None = None
 
@@ -201,7 +198,7 @@ class PowerFactoryExporter:
             project_name=self.project_name,
             powerfactory_user_profile=self.powerfactory_user_profile,
             powerfactory_path=self.powerfactory_path,
-            powerfactory_version=self.powerfactory_version,
+            powerfactory_service_pack=self.powerfactory_service_pack,
             python_version=self.python_version,
             logging_level=self.logging_level,
             log_file_path=self.log_file_path,
@@ -1697,7 +1694,7 @@ class PowerFactoryExporter:
 
         if load.GetClassName() is PFClassId.LOAD.value and load.typ_id is not None:
             voltage_system_type = VoltageSystemType[
-                ElementVoltageSystemType(t.cast("PowerFactoryTypes.LoadType", load.typ_id).systp).name
+                ElementVoltageSystemType(t.cast("PFTypes.LoadType", load.typ_id).systp).name
             ]
         else:
             voltage_system_type = VoltageSystemType[TerminalVoltageSystemType(terminal.systype).name]
@@ -2226,7 +2223,7 @@ class PowerFactoryExporter:
         The element states contain no node reference.
 
         Arguments:
-            elements {Sequence[ElementBase} -- sequence of one-sided connected PowerFactory objects
+            elements {Sequence[ElementBase | PFTypes.Line | PFTypes.Transformer2W} -- sequence of one-sided connected PowerFactory objects
 
         Keyword Arguments:
             grid_name {str} -- the name of the related grid
@@ -3937,9 +3934,9 @@ def export_powerfactory_data(  # noqa: PLR0913
     export_path: pathlib.Path,
     project_name: str,
     powerfactory_user_profile: str = "",
-    powerfactory_path: pathlib.Path = POWERFACTORY_PATH,
-    powerfactory_version: str = POWERFACTORY_VERSION,
-    python_version: str = PYTHON_VERSION,
+    powerfactory_path: pathlib.Path = DEFAULT_POWERFACTORY_PATH,
+    powerfactory_service_pack: int | None = None,
+    python_version: ValidPythonVersion = DEFAULT_PYTHON_VERSION,
     logging_level: int = logging.DEBUG,
     log_file_path: pathlib.Path | None = None,
     topology_name: str | None = None,
@@ -3958,9 +3955,9 @@ def export_powerfactory_data(  # noqa: PLR0913
         export_path {pathlib.Path} -- the directory where the exported json files are saved
         project_name {str} -- project name in PowerFactory to which the grid belongs
         powerfactory_user_profile {str} -- user profile for login in PowerFactory (default: {""})
-        powerfactory_path {pathlib.Path} -- installation directory of PowerFactory (hard-coded in interface.py)
-        powerfactory_version {str} -- version number of PowerFactory (hard-coded in interface.py)
-        python_version {str} -- version number of Python (hard-coded in interface.py)
+        powerfactory_path {pathlib.Path} -- installation directory of PowerFactory (default: {POWERFACTORY_PATH})
+        powerfactory_service_pack {int} -- the service pack version of PowerFactory (default: {None})
+        python_version {PYTHON_VERSIONS} -- the version of Python to be used for PowerFactory (default: {DEFAULT_PYTHON_VERSION})
         logging_level {int} -- flag for the level of logging criticality (default: {DEBUG})
         log_file_path {pathlib.Path} -- the file path of an external log file (default: {None})
         topology_name {str} -- the chosen file name for 'topology' data (default: {None})
@@ -3977,7 +3974,7 @@ def export_powerfactory_data(  # noqa: PLR0913
         export_path=export_path,
         powerfactory_user_profile=powerfactory_user_profile,
         powerfactory_path=powerfactory_path,
-        powerfactory_version=powerfactory_version,
+        powerfactory_service_pack=powerfactory_service_pack,
         python_version=python_version,
         logging_level=logging_level,
         log_file_path=log_file_path,
diff --git a/powerfactory_tools/exporter/load_power.py b/powerfactory_tools/versions/pf2022/exporter/load_power.py
similarity index 99%
rename from powerfactory_tools/exporter/load_power.py
rename to powerfactory_tools/versions/pf2022/exporter/load_power.py
index 12cf5be..10a10c2 100644
--- a/powerfactory_tools/exporter/load_power.py
+++ b/powerfactory_tools/versions/pf2022/exporter/load_power.py
@@ -1,6 +1,6 @@
 # :author: Sasan Jacob Rasti <sasan_jacob.rasti@tu-dresden.de>
 # :author: Sebastian Krahmer <sebastian.krahmer@tu-dresden.de>
-# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2023.
+# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2024.
 # :license: BSD 3-Clause
 
 from __future__ import annotations
@@ -33,9 +33,9 @@ from psdm.steadystate_case.controller import ControlUConst
 from psdm.steadystate_case.controller import QControlStrategy
 from psdm.topology.load import RatedPower
 
-from powerfactory_tools.constants import DecimalDigits
-from powerfactory_tools.constants import Exponents
-from powerfactory_tools.quantities import QuantityConverter as Qc
+from powerfactory_tools.versions.pf2022.constants import DecimalDigits
+from powerfactory_tools.versions.pf2022.constants import Exponents
+from powerfactory_tools.versions.pf2022.quantities import QuantityConverter as Qc
 
 if t.TYPE_CHECKING:
     from typing import TypedDict
diff --git a/powerfactory_tools/interface.py b/powerfactory_tools/versions/pf2022/interface.py
similarity index 96%
rename from powerfactory_tools/interface.py
rename to powerfactory_tools/versions/pf2022/interface.py
index 2aecbeb..23b4c64 100644
--- a/powerfactory_tools/interface.py
+++ b/powerfactory_tools/versions/pf2022/interface.py
@@ -1,6 +1,6 @@
 # :author: Sasan Jacob Rasti <sasan_jacob.rasti@tu-dresden.de>
 # :author: Sebastian Krahmer <sebastian.krahmer@tu-dresden.de>
-# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2023.
+# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2024.
 # :license: BSD 3-Clause
 
 from __future__ import annotations
@@ -21,21 +21,22 @@ from collections.abc import Sequence
 import loguru
 import pydantic
 
-from powerfactory_tools.constants import BaseUnits
 from powerfactory_tools.powerfactory_error_codes import ErrorCode
-from powerfactory_tools.powerfactory_types import CalculationCommand
-from powerfactory_tools.powerfactory_types import Currency
-from powerfactory_tools.powerfactory_types import FolderType
-from powerfactory_tools.powerfactory_types import MetricPrefix
-from powerfactory_tools.powerfactory_types import NetworkExtendedCalcType
-from powerfactory_tools.powerfactory_types import PFClassId
-from powerfactory_tools.powerfactory_types import ResultExportMode
-from powerfactory_tools.powerfactory_types import TimeSimulationNetworkCalcType
-from powerfactory_tools.powerfactory_types import TimeSimulationType
-from powerfactory_tools.powerfactory_types import UnitSystem
-from powerfactory_tools.powerfactory_types import ValidPFValue
 from powerfactory_tools.utils.io import CustomEncoder
 from powerfactory_tools.utils.io import FileType
+from powerfactory_tools.versions.pf2022.constants import BaseUnits
+from powerfactory_tools.versions.pf2022.data import PowerFactoryData
+from powerfactory_tools.versions.pf2022.types import CalculationCommand
+from powerfactory_tools.versions.pf2022.types import Currency
+from powerfactory_tools.versions.pf2022.types import FolderType
+from powerfactory_tools.versions.pf2022.types import MetricPrefix
+from powerfactory_tools.versions.pf2022.types import NetworkExtendedCalcType
+from powerfactory_tools.versions.pf2022.types import PFClassId
+from powerfactory_tools.versions.pf2022.types import ResultExportMode
+from powerfactory_tools.versions.pf2022.types import TimeSimulationNetworkCalcType
+from powerfactory_tools.versions.pf2022.types import TimeSimulationType
+from powerfactory_tools.versions.pf2022.types import UnitSystem
+from powerfactory_tools.versions.pf2022.types import ValidPFValue
 
 if t.TYPE_CHECKING:
     from collections.abc import Iterable
@@ -43,17 +44,24 @@ if t.TYPE_CHECKING:
 
     import typing_extensions as te
 
-    from powerfactory_tools.powerfactory_types import PowerFactoryTypes as PFTypes
+    from powerfactory_tools.versions.pf2022.types import PowerFactoryTypes as PFTypes
 
     T = t.TypeVar("T")
 
-POWERFACTORY_PATH = pathlib.Path("C:/Program Files/DIgSILENT")
-POWERFACTORY_VERSION = "2022 SP2"
-PYTHON_VERSION = "3.10"
-PATH_SEP = "/"
 
-VERSION = "2.1.0"
+# allowed Python versions
+class ValidPythonVersion(enum.Enum):
+    VERSION_3_6 = "3.6"
+    VERSION_3_7 = "3.7"
+    VERSION_3_8 = "3.8"
+    VERSION_3_9 = "3.9"
+    VERSION_3_10 = "3.10"
+
 
+PATH_SEP = "/"
+POWERFACTORY_VERSION = "PowerFactory 2022"
+DEFAULT_POWERFACTORY_PATH = pathlib.Path("C:/Program Files/DIgSILENT")
+DEFAULT_PYTHON_VERSION = ValidPythonVersion.VERSION_3_10
 
 config = pydantic.ConfigDict(use_enum_values=True)
 
@@ -88,37 +96,15 @@ DEFAULT_PROJECT_UNIT_SETTING = ProjectUnitSetting(
 )
 
 
-@dataclasses.dataclass
-class PowerFactoryData:
-    date: dt.date
-    project_name: str
-    grid_name: str
-    external_grids: Sequence[PFTypes.ExternalGrid]
-    terminals: Sequence[PFTypes.Terminal]
-    lines: Sequence[PFTypes.Line]
-    transformers_2w: Sequence[PFTypes.Transformer2W]
-    transformers_3w: Sequence[PFTypes.Transformer3W]
-    loads: Sequence[PFTypes.Load]
-    loads_lv: Sequence[PFTypes.LoadLV]
-    loads_mv: Sequence[PFTypes.LoadMV]
-    generators: Sequence[PFTypes.Generator]
-    pv_systems: Sequence[PFTypes.PVSystem]
-    couplers: Sequence[PFTypes.Coupler]
-    switches: Sequence[PFTypes.Switch]
-    bfuses: Sequence[PFTypes.BFuse]
-    efuses: Sequence[PFTypes.EFuse]
-    ac_current_sources: Sequence[PFTypes.AcCurrentSource]
-
-
 @pydantic.dataclasses.dataclass
 class PowerFactoryInterface:
     project_name: str
+    powerfactory_path: pathlib.Path = DEFAULT_POWERFACTORY_PATH
+    powerfactory_service_pack: int | None = None
     powerfactory_user_profile: str | None = None
     powerfactory_user_password: str | None = None
-    powerfactory_path: pathlib.Path = POWERFACTORY_PATH
-    powerfactory_version: str = POWERFACTORY_VERSION
     powerfactory_ini_name: str | None = None
-    python_version: str = PYTHON_VERSION
+    python_version: ValidPythonVersion = DEFAULT_PYTHON_VERSION
     logging_level: int = logging.DEBUG
     log_file_path: pathlib.Path | None = None
 
@@ -126,8 +112,8 @@ class PowerFactoryInterface:
         try:
             self._set_logging_handler(self.log_file_path)
             loguru.logger.info("Starting PowerFactory Interface...")
-            pf = self.load_powerfactory_module_from_path()
-            self.app = self.connect_to_app(pf)
+            pfm = self.load_powerfactory_module_from_path()
+            self.app = self.connect_to_app(pfm)
             self.project = self.connect_to_project(self.project_name)
             self.load_project_setting_folders_from_pf_db()
             self.stash_unit_conversion_settings()
@@ -168,6 +154,60 @@ class PowerFactoryInterface:
     ) -> None:
         self.close()
 
+    def load_powerfactory_module_from_path(self) -> PFTypes.PowerFactoryModule:
+        loguru.logger.debug("Loading PowerFactory Python module...")
+        module_path = (
+            self.powerfactory_path / POWERFACTORY_VERSION / "Python" / self.python_version.value
+            if self.powerfactory_service_pack is None
+            else self.powerfactory_path
+            / (POWERFACTORY_VERSION + f" SP{self.powerfactory_service_pack}")
+            / "Python"
+            / self.python_version.value
+        )
+        spec = importlib.util.spec_from_file_location(
+            "powerfactory",
+            module_path / "powerfactory.pyd",
+        )
+        if (spec is None) or (spec.loader is None):
+            msg = "Could not load PowerFactory Module."
+            raise RuntimeError(msg)
+
+        pfm = importlib.util.module_from_spec(spec)
+        spec.loader.exec_module(pfm)
+        return t.cast("PFTypes.PowerFactoryModule", pfm)
+
+    def connect_to_app(self, pfm: PFTypes.PowerFactoryModule) -> PFTypes.Application:
+        """Connect to PowerFactory Application.
+
+        Arguments:
+            pfm {PFTypes.PowerFactoryModule} -- the Python module contributed via the PowerFactory system installation
+
+        Returns:
+            PFTypes.Application -- the application handle (root)
+        """
+
+        loguru.logger.debug("Connecting to PowerFactory application...")
+        if self.powerfactory_ini_name is None:
+            command_line_arg = None
+        else:
+            ini_path = (
+                self.powerfactory_path / POWERFACTORY_VERSION / (self.powerfactory_ini_name + ".ini")
+                if self.powerfactory_service_pack is None
+                else self.powerfactory_path
+                / (POWERFACTORY_VERSION + f" SP{self.powerfactory_service_pack}")
+                / (self.powerfactory_ini_name + ".ini")
+            )
+            command_line_arg = '/ini "' + str(ini_path) + '"'
+        try:
+            return pfm.GetApplicationExt(
+                self.powerfactory_user_profile,
+                self.powerfactory_user_password,
+                command_line_arg,
+            )
+        except pfm.ExitError as element:
+            msg = "Could not start application."
+            raise RuntimeError(msg) from element
+
     def load_project_setting_folders_from_pf_db(self) -> None:
         self.project_settings = self.load_project_settings_dir_from_pf()
         self.settings_dir = self.load_settings_dir_from_pf()
@@ -197,23 +237,6 @@ class PowerFactoryInterface:
         self.ext_data_dir = self.project_settings.extDataDir
         loguru.logger.debug("Loading all project folders... Done")
 
-    def load_powerfactory_module_from_path(self) -> PFTypes.PowerFactoryModule:
-        loguru.logger.debug("Loading PowerFactory Python module...")
-        module_path = (
-            self.powerfactory_path / ("PowerFactory " + self.powerfactory_version) / "Python" / self.python_version
-        )
-        spec = importlib.util.spec_from_file_location(
-            "powerfactory",
-            module_path / "powerfactory.pyd",
-        )
-        if (spec is None) or (spec.loader is None):
-            msg = "Could not load PowerFactory Module."
-            raise RuntimeError(msg)
-
-        pfm = importlib.util.module_from_spec(spec)
-        spec.loader.exec_module(pfm)
-        return t.cast("PFTypes.PowerFactoryModule", pfm)
-
     def load_settings_dir_from_pf(self) -> PFTypes.DataDir:
         loguru.logger.debug("Loading settings from PowerFactory...")
         _settings_dirs = self.elements_of(
@@ -260,41 +283,6 @@ class PowerFactoryInterface:
 
         loguru.logger.info("Closing PowerFactory Interface... Done.")
 
-    def connect_to_app(
-        self,
-        pf: PFTypes.PowerFactoryModule,
-    ) -> PFTypes.Application:
-        """Connect to PowerFactory Application.
-
-        Arguments:
-            pf {PFTypes.PowerFactoryModule} -- the Python module contributed via the PowerFactory system installation
-
-        Returns:
-            PFTypes.Application -- the application handle (root)
-        """
-
-        loguru.logger.debug("Connecting to PowerFactory application...")
-        if self.powerfactory_ini_name is None:
-            command_line_arg = None
-        else:
-            ini_path = (
-                self.powerfactory_path
-                / ("PowerFactory " + self.powerfactory_version)
-                / (self.powerfactory_ini_name + ".ini")
-            )
-            command_line_arg = '/ini "' + str(ini_path) + '"'
-        try:
-            return pf.GetApplicationExt(
-                self.powerfactory_user_profile,
-                self.powerfactory_user_password,
-                command_line_arg,
-            )
-        except pf.ExitError as element:
-            error_code = self.resolve_pf_error_code(element)
-            msg = f"Could not start application. Error code: {error_code.value} - {error_code.name}"
-            loguru.logger.exception(msg)
-            raise RuntimeError(msg) from element
-
     def connect_to_project(self, project_name: str) -> PFTypes.Project:
         """Connect to a PowerFactory project.
 
@@ -336,6 +324,7 @@ class PowerFactoryInterface:
         else:
             msg = f"Study case {study_case_name} does not exist."
             raise RuntimeError(msg)
+
         return self.study_case(study_case_name)  # type: ignore [return-value]
 
     def switch_scenario(self, scenario_name: str) -> None:
@@ -679,14 +668,6 @@ class PowerFactoryInterface:
             msg = "Could not deactivate project."
             raise RuntimeError(msg)
 
-    def subloads_of(
-        self,
-        load: PFTypes.LoadLV,
-        /,
-    ) -> Sequence[PFTypes.LoadLVP]:
-        elements = self.elements_of(load, pattern="*." + PFClassId.LOAD_LV_PART.value)
-        return [t.cast("PFTypes.LoadLVP", element) for element in elements]
-
     def variable_monitor(
         self,
         name: str = "*",
@@ -1300,56 +1281,6 @@ class PowerFactoryInterface:
         )
         return [t.cast("PFTypes.Load", element) for element in elements]
 
-    def load_lv(
-        self,
-        name: str = "*",
-        /,
-        *,
-        grid_name: str = "*",
-    ) -> PFTypes.LoadLV | None:
-        return self.first_of(self.loads_lv(name, grid_name=grid_name))
-
-    def loads_lv(
-        self,
-        name: str = "*",
-        /,
-        *,
-        grid_name: str = "*",
-        calc_relevant: bool = False,
-    ) -> Sequence[PFTypes.LoadLV]:
-        elements = self.grid_elements(
-            class_name=PFClassId.LOAD_LV.value,
-            name=name,
-            grid_name=grid_name,
-            calc_relevant=calc_relevant,
-        )
-        return [t.cast("PFTypes.LoadLV", element) for element in elements]
-
-    def load_mv(
-        self,
-        name: str = "*",
-        /,
-        *,
-        grid_name: str = "*",
-    ) -> PFTypes.LoadMV | None:
-        return self.first_of(self.loads_mv(name, grid_name=grid_name))
-
-    def loads_mv(
-        self,
-        name: str = "*",
-        /,
-        *,
-        grid_name: str = "*",
-        calc_relevant: bool = False,
-    ) -> Sequence[PFTypes.LoadMV]:
-        elements = self.grid_elements(
-            class_name=PFClassId.LOAD_MV.value,
-            name=name,
-            grid_name=grid_name,
-            calc_relevant=calc_relevant,
-        )
-        return [t.cast("PFTypes.LoadMV", element) for element in elements]
-
     def generator(
         self,
         name: str = "*",
@@ -2499,3 +2430,62 @@ class PowerFactoryInterface:
     ) -> bool:
         """Return true if branch fuse."""
         return fuse.bus1 is not None or fuse.bus2 is not None
+
+    ## The following may be part of version inconsistent behavior
+    def subloads_of(
+        self,
+        load: PFTypes.LoadLV,
+        /,
+    ) -> Sequence[PFTypes.LoadLVP]:
+        elements = self.elements_of(load, pattern="*." + PFClassId.LOAD_LV_PART.value)
+        return [t.cast("PFTypes.LoadLVP", element) for element in elements]
+
+    def load_lv(
+        self,
+        name: str = "*",
+        /,
+        *,
+        grid_name: str = "*",
+    ) -> PFTypes.LoadLV | None:
+        return self.first_of(self.loads_lv(name, grid_name=grid_name))
+
+    def loads_lv(
+        self,
+        name: str = "*",
+        /,
+        *,
+        grid_name: str = "*",
+        calc_relevant: bool = False,
+    ) -> Sequence[PFTypes.LoadLV]:
+        elements = self.grid_elements(
+            class_name=PFClassId.LOAD_LV.value,
+            name=name,
+            grid_name=grid_name,
+            calc_relevant=calc_relevant,
+        )
+        return [t.cast("PFTypes.LoadLV", element) for element in elements]
+
+    def load_mv(
+        self,
+        name: str = "*",
+        /,
+        *,
+        grid_name: str = "*",
+    ) -> PFTypes.LoadMV | None:
+        return self.first_of(self.loads_mv(name, grid_name=grid_name))
+
+    def loads_mv(
+        self,
+        name: str = "*",
+        /,
+        *,
+        grid_name: str = "*",
+        calc_relevant: bool = False,
+    ) -> Sequence[PFTypes.LoadMV]:
+        elements = self.grid_elements(
+            class_name=PFClassId.LOAD_MV.value,
+            name=name,
+            grid_name=grid_name,
+            calc_relevant=calc_relevant,
+        )
+        return [t.cast("PFTypes.LoadMV", element) for element in elements]
diff --git a/powerfactory_tools/quantities.py b/powerfactory_tools/versions/pf2022/quantities.py
similarity index 98%
rename from powerfactory_tools/quantities.py
rename to powerfactory_tools/versions/pf2022/quantities.py
index 09697af..e5e83a9 100644
--- a/powerfactory_tools/quantities.py
+++ b/powerfactory_tools/versions/pf2022/quantities.py
@@ -1,6 +1,6 @@
 # :author: Sasan Jacob Rasti <sasan_jacob.rasti@tu-dresden.de>
 # :author: Sebastian Krahmer <sebastian.krahmer@tu-dresden.de>
-# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2023.
+# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2024.
 # :license: BSD 3-Clause
 
 from psdm.quantities.multi_phase import ActivePower
diff --git a/powerfactory_tools/powerfactory_types.py b/powerfactory_tools/versions/pf2022/types.py
similarity index 89%
rename from powerfactory_tools/powerfactory_types.py
rename to powerfactory_tools/versions/pf2022/types.py
index ece5fc5..f7b2e92 100644
--- a/powerfactory_tools/powerfactory_types.py
+++ b/powerfactory_tools/versions/pf2022/types.py
@@ -1,17 +1,15 @@
 # :author: Sasan Jacob Rasti <sasan_jacob.rasti@tu-dresden.de>
 # :author: Sebastian Krahmer <sebastian.krahmer@tu-dresden.de>
-# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2023.
+# :copyright: Copyright (c) Institute of Electrical Power Systems and High Voltage Engineering - TU Dresden, 2022-2024.
 # :license: BSD 3-Clause
 
 from __future__ import annotations
 
 import enum
-from typing import TYPE_CHECKING
-from typing import Any
-from typing import Literal
+import typing as t
 from typing import Protocol
 
-if TYPE_CHECKING:
+if t.TYPE_CHECKING:
     from collections.abc import Sequence
 
 
@@ -106,6 +104,46 @@ class FolderType(enum.Enum):
     V_CONTROL_CURVES = "ucc"
 
 
+class MetricPrefix(enum.Enum):
+    a = "a"
+    f = "f"
+    p = "p"
+    n = "n"
+    u = "u"
+    m = "m"
+    EMPTY = ""
+    k = "k"
+    M = "M"
+    G = "G"
+    T = "T"
+    P = "P"
+    E = "E"
+
+
+class Currency(enum.Enum):
+    USD = "USD"
+    EUR = "EUR"
+    JPY = "JPY"
+    GBP = "GBP"
+    AUD = "AUD"
+    CAD = "CAD"
+    CHF = "CHF"
+    CNY = "CNY"
+    SEK = "SEK"
+    MXN = "MXN"
+    NZD = "NZD"
+    SGD = "SGD"
+    HKD = "HKD"
+    NOK = "NOK"
+    KRW = "KRW"
+    TRY = "TRY"
+    INR = "INR"
+    RUB = "RUB"
+    BRL = "BRL"
+    ZAR = "ZAR"
+    CLP = "CLP"
+
+
 class LocalQCtrlMode(enum.Enum):
     COSPHI_CONST = "constc"
     COSPHI_P = "cpchar"
@@ -341,46 +379,6 @@ class TrfNeutralPointState(enum.IntEnum):
     ISOLATED = 1
 
 
-class MetricPrefix(enum.Enum):
-    a = "a"
-    f = "f"
-    p = "p"
-    n = "n"
-    u = "u"
-    m = "m"
-    EMPTY = ""
-    k = "k"
-    M = "M"
-    G = "G"
-    T = "T"
-    P = "P"
-    E = "E"
-
-
-class Currency(enum.Enum):
-    USD = "USD"
-    EUR = "EUR"
-    JPY = "JPY"
-    GBP = "GBP"
-    AUD = "AUD"
-    CAD = "CAD"
-    CHF = "CHF"
-    CNY = "CNY"
-    SEK = "SEK"
-    MXN = "MXN"
-    NZD = "NZD"
-    SGD = "SGD"
-    HKD = "HKD"
-    NOK = "NOK"
-    KRW = "KRW"
-    TRY = "TRY"
-    INR = "INR"
-    RUB = "RUB"
-    BRL = "BRL"
-    ZAR = "ZAR"
-    CLP = "CLP"
-
-
 class ISym(enum.IntEnum):
     SYM = 0
     ASYM = 1
@@ -536,7 +534,7 @@ class ResultExportMode(enum.IntEnum):
     TEXT_FILE = 4
     PSSPLT_VERSION_2 = 5
     CSV = 6
-    DATABSE = 7
+    DATABASE = 7
 
 
 class ResultExportVariableSelection(enum.IntEnum):
@@ -572,7 +570,7 @@ class ResultExportNumberFormat(enum.IntEnum):
 
 
 class PowerFactoryTypes:
-    class DataObject(Protocol):
+    class DataObject(t.Protocol):
         loc_name: str
         fold_id: PowerFactoryTypes.DataObject | None
 
@@ -624,12 +622,12 @@ class PowerFactoryTypes:
             /,
         ) -> int: ...
 
-    class DataDir(DataObject, Protocol): ...
+    class DataDir(DataObject, t.Protocol): ...
 
-    class GridDiagram(DataObject, Protocol):  # PFClassId.GRID_GRAPHIC
+    class GridDiagram(DataObject, t.Protocol):  # PFClassId.GRID_GRAPHIC
         ...
 
-    class Graph(DataObject, Protocol):
+    class Graph(DataObject, t.Protocol):
         sSymName: str  # noqa: N815
         pDataObj: PowerFactoryTypes.DataObject | None  # noqa: N815
         rCenterX: float  # noqa: N815
@@ -643,20 +641,20 @@ class PowerFactoryTypes:
         iIndLS: int  # noqa: N815
         iVis: bool  # noqa: N815
 
-    class Project(DataObject, Protocol):
+    class Project(DataObject, t.Protocol):
         pPrjSettings: PowerFactoryTypes.ProjectSettings  # noqa: N815
 
         def Deactivate(self) -> bool:  # noqa: N802
             ...
 
-    class Scenario(DataObject, Protocol):  # PFClassId.SCENARIO
+    class Scenario(DataObject, t.Protocol):  # PFClassId.SCENARIO
         def Activate(self) -> bool:  # noqa: N802
             ...
 
         def Deactivate(self) -> bool:  # noqa: N802
             ...
 
-    class StudyCase(DataObject, Protocol):  # PFClassId.STUDY_CASE
+    class StudyCase(DataObject, t.Protocol):  # PFClassId.STUDY_CASE
         iStudyTime: int  # noqa: N815
 
         def Activate(self) -> bool:  # noqa: N802
@@ -665,12 +663,12 @@ class PowerFactoryTypes:
         def ApplyNetworkState(  # noqa: N802
             self,
             other: PowerFactoryTypes.DataObject,  # the other study case to copy from: grids, scenarios and network variations configuration
-        ) -> Literal[0, 1, 2, 3, 4, 5]: ...
+        ) -> t.Literal[0, 1, 2, 3, 4, 5]: ...
 
         def ApplyStudyTime(  # noqa: N802
             self,
             other: PowerFactoryTypes.DataObject,  # the other study case to copy from: study time
-        ) -> Literal[0, 1, 2, 3, 4]: ...
+        ) -> t.Literal[0, 1, 2, 3, 4]: ...
 
         def Consolidate(self) -> bool:  # noqa: N802
             ...
@@ -683,7 +681,7 @@ class PowerFactoryTypes:
             date_time: int,  # Seconds since 01.01.1970 00:00:00.
         ) -> None: ...
 
-    class GridVariant(DataObject, Protocol):  # PFClassId.VARIANT
+    class GridVariant(DataObject, t.Protocol):  # PFClassId.VARIANT
         def Activate(self) -> bool:  # noqa: N802
             ...
 
@@ -698,7 +696,7 @@ class PowerFactoryTypes:
             /,
         ) -> bool: ...
 
-    class GridVariantStage(DataObject, Protocol):  # PFClassId.VARIANT_STAGE
+    class GridVariantStage(DataObject, t.Protocol):  # PFClassId.VARIANT_STAGE
         tAcTime: str  # noqa: N815
         iExclude: int  # noqa: N815
 
@@ -708,7 +706,7 @@ class PowerFactoryTypes:
         def GetVariation(self) -> PowerFactoryTypes.GridVariant:  # noqa: N802
             ...
 
-    class ProjectSettings(DataObject, Protocol):  # PFClassId.PROJECT_SETTINGS
+    class ProjectSettings(DataObject, t.Protocol):  # PFClassId.PROJECT_SETTINGS
         extDataDir: str  # noqa: N815
         ilenunit: UnitSystem
         clenexp: MetricPrefix  # Lengths
@@ -716,7 +714,7 @@ class PowerFactoryTypes:
         cspqexpgen: MetricPrefix  # Generators etc.
         currency: Currency
 
-    class UnitConversionSetting(DataObject, Protocol):
+    class UnitConversionSetting(DataObject, t.Protocol):
         filtclass: Sequence[str]
         filtvar: str
         digunit: str
@@ -726,9 +724,9 @@ class PowerFactoryTypes:
         ufacA: float  # noqa: N815
         ufacB: float  # noqa: N815
 
-    class Substation(DataObject, Protocol): ...
+    class Substation(DataObject, t.Protocol): ...
 
-    class LoadType(DataObject, Protocol):  # PFClassId.LOAD_TYPE_GENERAL
+    class LoadType(DataObject, t.Protocol):  # PFClassId.LOAD_TYPE_GENERAL
         loddy: float  # portion of dynamic part of ZIP load model in RMS simulation (100 = 100% dynamic)
         systp: VoltageSystemType
         phtech: LoadPhaseConnectionType
@@ -752,56 +750,10 @@ class PowerFactoryTypes:
         Prp: float  # for harmonic load model type IMPEDANCE_TYPE_2; static portion in percent
         pcf: float  # for harmonic load model type IMPEDANCE_TYPE_2; load factor correction in percent
 
-    class LoadTypeLV(DataObject, Protocol):  # PFClassId.LOAD_TYPE_LV
-        Smax: float  # maximum apparent power for a single residential unit, per default in kVA
-        cosphi: float  # power factor
-        ginf: float  # simultaneity factor
-
-        iLodTyp: PowerModelType  # composite (ZIP) / exponent  # noqa: N815
-        aP: float  # noqa: N815  # const. power part of the active power in relation to ZIP load model
-        bP: float  # noqa: N815  # const. current part of the active power in relation to ZIP load model
-        cP: float  # noqa: N815  # const. impedance part of the active power in relation to ZIP load model
-        aQ: float  # noqa: N815  # const. power part of the reactive power in relation to ZIP load model
-        bQ: float  # noqa: N815  # const. current part of the reactive power in relation to ZIP load model
-        cQ: float  # noqa: N815  # const. impedance part of the reactive power in relation to ZIP load model
-
-        eP: float  # noqa: N815  # exponent of the active power in relation to exponential load model
-        eQ: float  # noqa: N815  # exponent of the reactive power in relation to exponential load model
-
-    class LoadTypeMV(DataObject, Protocol):  # PFClassId.LOAD_TYPE_MV  # is an equivalent of a distribution transformer
-        strn: float  # rated power, per default in MVA
-        frnom: float  # nominal frequency
-        tratio: float  # transformer ratio
-        phtech: LoadPhaseConnectionType
-
-        uktr: float  # short-circuit voltage in percentage (pos. seq.)
-        pcutr: float  # cupper losses, per default in kW
-
-        iZzero: bool  # 1 zero seq. impedance is given; 0 zero seq. impedance is not given  # noqa: N815
-        uk0tr: float  # short-circuit voltage in percentage (zero. seq.)
-        ur0tr: float  # real part of uk0tr
-
-        pfe: float  # iron losses, per default in kW
-        dutap: float  # additional voltage per tap changer step in percentage
-        nntap0: int  # neutral position of tap changer
-        ntpmn: int  # lowest position of tap changer
-        ntpmx: int  # highest position of tap changer
-
-        LodTyp: PowerModelType  # composite (ZIP) / exponent
-        aP: float  # noqa: N815  # const. power part of the active power in relation to ZIP load model
-        bP: float  # noqa: N815  # const. current part of the active power in relation to ZIP load model
-        cP: float  # noqa: N815  # const. impedance part of the active power in relation to ZIP load model
-        aQ: float  # noqa: N815  # const. power part of the reactive power in relation to ZIP load model
-        bQ: float  # noqa: N815  # const. current part of the reactive power in relation to ZIP load model
-        cQ: float  # noqa: N815  # const. impedance part of the reactive power in relation to ZIP load model
-
-        eP: float  # noqa: N815  # exponent of the active power in relation to exponential load model
-        eQ: float  # noqa: N815  # exponent of the reactive power in relation to exponential load model
-
-    class SourceTypeHarmonicCurrent(DataObject, Protocol):  # PFClassId.SOURCE_TYPE_HARMONIC_CURRENT
+    class SourceTypeHarmonicCurrent(DataObject, t.Protocol):  # PFClassId.SOURCE_TYPE_HARMONIC_CURRENT
         i_usym: HarmonicSourceSystemType
 
-    class LineType(DataObject, Protocol):  # PFClassId.LINE_TYPE
+    class LineType(DataObject, t.Protocol):  # PFClassId.LINE_TYPE
         uline: float  # rated voltage (kV)
         sline: float  # rated current (kA) when installed in soil
         InomAir: float  # rated current (kA) when installed in air
@@ -820,7 +772,7 @@ class PowerFactoryTypes:
         systp: VoltageSystemType
         frnom: float  # nominal frequency the values x and b apply
 
-    class LineNType(LineType, Protocol):
+    class LineNType(LineType, t.Protocol):
         rnline: float  # resistance (Ohm/km) natural neutral components
         rpnline: float  # resistance (Ohm/km) natural neutral-line couple components
         xnline: float  # reactance (Ohm/km) natural neutral components
@@ -830,7 +782,7 @@ class PowerFactoryTypes:
         bnline: float  # susceptance (µS/km) natural neutral components
         bpnline: float  # susceptance (µS/km) natural neutral-line couple components
 
-    class Transformer2WType(DataObject, Protocol):  # PFClassId.TRANSFORMER_2W_TYPE
+    class Transformer2WType(DataObject, t.Protocol):  # PFClassId.TRANSFORMER_2W_TYPE
         utrn_l: float  # reference voltage LV side
         utrn_h: float  # reference voltage HV side
         pfe: float  # Iron losses
@@ -870,15 +822,15 @@ class PowerFactoryTypes:
 
         nt2ph: TrfPhaseTechnology
 
-    class Transformer3WType(DataObject, Protocol):  # PFClassId.TRANSFORMER_3W_TYPE
+    class Transformer3WType(DataObject, t.Protocol):  # PFClassId.TRANSFORMER_3W_TYPE
         ...
 
-    class SwitchType(DataObject, Protocol):  # PFClassId.SWITCH
+    class SwitchType(DataObject, t.Protocol):  # PFClassId.SWITCH
         Inom: float
         R_on: float
         X_on: float
 
-    class Coupler(DataObject, Protocol):  # PFClassId.COUPLER
+    class Coupler(DataObject, t.Protocol):  # PFClassId.COUPLER
         bus1: PowerFactoryTypes.StationCubicle | None
         bus2: PowerFactoryTypes.StationCubicle | None
         typ_id: PowerFactoryTypes.SwitchType | None
@@ -886,7 +838,7 @@ class PowerFactoryTypes:
         isclosed: bool
         desc: Sequence[str]
 
-    class Grid(DataObject, Protocol):  # PFClassId.GRID
+    class Grid(DataObject, t.Protocol):  # PFClassId.GRID
         pDiagram: PowerFactoryTypes.GridDiagram | None  # noqa: N815
         frnom: float  # nominal frequency
 
@@ -896,12 +848,12 @@ class PowerFactoryTypes:
         def Deactivate(self) -> bool:  # noqa: N802
             ...
 
-    class LineBase(DataObject, Protocol):
+    class LineBase(DataObject, t.Protocol):
         cDisplayName: str  # noqa: N815
         desc: Sequence[str]
         outserv: bool
 
-    class Terminal(DataObject, Protocol):  # PFClassId.TERMINAL
+    class Terminal(DataObject, t.Protocol):  # PFClassId.TERMINAL
         cDisplayName: str  # noqa: N815
         ciEnergized: bool  # noqa: N815
         desc: Sequence[str]
@@ -932,13 +884,13 @@ class PowerFactoryTypes:
         def IsInternalNodeInStation(self) -> bool:  # noqa: N802
             ...
 
-    class StationCubicle(DataObject, Protocol):  # PFClassId.CUBICLE
+    class StationCubicle(DataObject, t.Protocol):  # PFClassId.CUBICLE
         cterm: PowerFactoryTypes.Terminal
         obj_id: PowerFactoryTypes.Line | PowerFactoryTypes.Element | None
         nphase: int
         cPhInfo: str  # noqa: N815
 
-    class Transformer2W(LineBase, Protocol):  # PFClassId.TRANSFORMER_2W
+    class Transformer2W(LineBase, t.Protocol):  # PFClassId.TRANSFORMER_2W
         buslv: PowerFactoryTypes.StationCubicle | None
         bushv: PowerFactoryTypes.StationCubicle | None
         ntnum: int
@@ -955,7 +907,7 @@ class PowerFactoryTypes:
         xe0tr_h: float
         xe0tr_l: float
 
-    class Transformer3W(LineBase, Protocol):  # PFClassId.TRANSFORMER_3W
+    class Transformer3W(LineBase, t.Protocol):  # PFClassId.TRANSFORMER_3W
         buslv: PowerFactoryTypes.StationCubicle | None
         busmv: PowerFactoryTypes.StationCubicle | None
         bushv: PowerFactoryTypes.StationCubicle | None
@@ -965,12 +917,12 @@ class PowerFactoryTypes:
         n3tapm: int
         n3taph: int
 
-    class ControllerBase(DataObject, Protocol):
+    class ControllerBase(DataObject, t.Protocol):
         c_pmod: PowerFactoryTypes.CompoundModel | None
 
-    class SecondaryController(ControllerBase, Protocol): ...
+    class SecondaryController(ControllerBase, t.Protocol): ...
 
-    class StationController(ControllerBase, Protocol):  # PFClassId.STATION_CONTROLLER
+    class StationController(ControllerBase, t.Protocol):  # PFClassId.STATION_CONTROLLER
         i_ctrl: ExternalQCtrlMode
         qu_char: QChar
         qsetp: float
@@ -997,14 +949,14 @@ class PowerFactoryTypes:
         p_over: float
         i_phase: CtrlVoltageRef
 
-    class Element(DataObject, Protocol):
+    class Element(DataObject, t.Protocol):
         desc: Sequence[str]
 
-    class DeviceBase(Element, Protocol):
+    class DeviceBase(Element, t.Protocol):
         pf_recap: PFRecap
         outserv: bool
 
-    class GeneratorBase(DeviceBase, Protocol):
+    class GeneratorBase(DeviceBase, t.Protocol):
         bus1: PowerFactoryTypes.StationCubicle | None
         scale0: float
 
@@ -1038,21 +990,21 @@ class PowerFactoryTypes:
         usetp: float
         phtech: GeneratorPhaseConnectionType
 
-    class QPCharacteristic(DataObject, Protocol):
+    class QPCharacteristic(DataObject, t.Protocol):
         inputmod: bool
 
-    class Generator(GeneratorBase, Protocol):  # PFClassId.GENERATOR
+    class Generator(GeneratorBase, t.Protocol):  # PFClassId.GENERATOR
         aCategory: GeneratorSystemType  # noqa: N815
         c_psecc: PowerFactoryTypes.SecondaryController | None
 
-    class PVSystem(GeneratorBase, Protocol):  # PFClassId.PVSYSTEM
+    class PVSystem(GeneratorBase, t.Protocol):  # PFClassId.PVSYSTEM
         uk: float
         Pcu: float
 
-    class LoadBase(DeviceBase, Protocol):
+    class LoadBase(DeviceBase, t.Protocol):
         typ_id: PowerFactoryTypes.LoadType | PowerFactoryTypes.LoadTypeLV | PowerFactoryTypes.LoadTypeMV | None
 
-    class LoadBase3Ph(LoadBase, Protocol):
+    class LoadBase3Ph(LoadBase, t.Protocol):
         bus1: PowerFactoryTypes.StationCubicle | None
         scale0: float
 
@@ -1077,63 +1029,18 @@ class PowerFactoryTypes:
         coslinis: float
         coslinit: float
 
-    class Load(LoadBase3Ph, Protocol):  # PFClassId.LOAD
+    class Load(LoadBase3Ph, t.Protocol):  # PFClassId.LOAD
         typ_id: PowerFactoryTypes.LoadType | None
         mode_inp: ModeInpLoad
         i_sym: ISym
         u0: float
         phtech: LoadPhaseConnectionType
 
-    class LoadLVP(LoadBase, Protocol):  # PFClassId.LOAD_LV_PART
-        typ_id: PowerFactoryTypes.LoadTypeLV | None
-        iopt_inp: IOpt
-        elini: float
-        cplinia: float
-        slini: float
-        plini: float
-        qlini: float
-        ilini: float
-        coslini: float
-        ulini: float
-        pnight: float
-        cSav: float  # noqa: N815
-        cSmax: float  # noqa: N815
-        ccosphi: float
-        phtech: LoadLVPhaseConnectionType
-
-    class LoadLV(LoadBase3Ph, LoadLVP, Protocol):  # PFClassId.LOAD_LV
-        typ_id: PowerFactoryTypes.LoadTypeLV | None
-        i_sym: ISym
-        lodparts: Sequence[PowerFactoryTypes.LoadLVP]
-        phtech: LoadLVPhaseConnectionType
-
-    class LoadMV(LoadBase3Ph, Protocol):  # PFClassId.LOAD_MV
-        typ_id: PowerFactoryTypes.LoadTypeMV | None
-        mode_inp: ModeInpMV
-        ci_sym: ISym
-        elini: float
-        cplinia: float
-        sgini: float
-        sginir: float
-        sginis: float
-        sginit: float
-        pgini: float
-        pginir: float
-        pginis: float
-        pginit: float
-        cosgini: float
-        cosginir: float
-        cosginis: float
-        cosginit: float
-        gscale: float
-        pfg_recap: PFRecap
-        phtech: LoadPhaseConnectionType
-
-    class Switch(DataObject, Protocol):  # PFClassId.SWITCH
+    class Switch(DataObject, t.Protocol):  # PFClassId.SWITCH
         fold_id: PowerFactoryTypes.StationCubicle
         isclosed: bool  # 0:open; 1:closed
 
-    class Line(LineBase, Protocol):  # PFClassId.LINE
+    class Line(LineBase, t.Protocol):  # PFClassId.LINE
         bus1: PowerFactoryTypes.StationCubicle | None
         bus2: PowerFactoryTypes.StationCubicle | None
         nlnum: int  # no. of parallel lines
@@ -1143,13 +1050,13 @@ class PowerFactoryTypes:
         Inom_a: float  # nominal current (actual)
         typ_id: PowerFactoryTypes.LineType | None
 
-    class FuseType(DataObject, Protocol):  # PFClassId.FUSE_TYPE
+    class FuseType(DataObject, t.Protocol):  # PFClassId.FUSE_TYPE
         urat: float  # rated voltage
         irat: float  # rated current
         frq: float  # nominal frequency
         itype: FuseCharacteristicType
 
-    class Fuse(DataObject, Protocol):  # PFClassId.FUSE
+    class Fuse(DataObject, t.Protocol):  # PFClassId.FUSE
         desc: Sequence[str]
         typ_id: PowerFactoryTypes.FuseType | None
         on_off: bool  # closed = 1; open = 0
@@ -1157,16 +1064,16 @@ class PowerFactoryTypes:
         bus1: PowerFactoryTypes.StationCubicle | None
         bus2: PowerFactoryTypes.StationCubicle | None
 
-    class BFuse(Fuse, Protocol): ...
+    class BFuse(Fuse, t.Protocol): ...
 
-    class EFuse(Fuse, Protocol):
+    class EFuse(Fuse, t.Protocol):
         fold_id: PowerFactoryTypes.StationCubicle
         cn_bus: PowerFactoryTypes.Terminal
         cbranch: PowerFactoryTypes.LineBase | PowerFactoryTypes.Element | PowerFactoryTypes.Fuse
         bus1: None
         bus2: None
 
-    class ExternalGrid(DataObject, Protocol):  # PFClassId.EXTERNAL_GRID
+    class ExternalGrid(DataObject, t.Protocol):  # PFClassId.EXTERNAL_GRID
         bustp: BusType
         bus1: PowerFactoryTypes.StationCubicle | None
         desc: Sequence[str]
@@ -1178,14 +1085,14 @@ class PowerFactoryTypes:
         snssmin: float  # in MVA
         outserv: bool
 
-    class SourceBase(DataObject, Protocol):
+    class SourceBase(DataObject, t.Protocol):
         bus1: PowerFactoryTypes.StationCubicle | None
         outserv: bool
         nphase: int
         desc: Sequence[str]
         c_pmod: PowerFactoryTypes.CompoundModel | None  # Compound Parent Model/Template
 
-    class AcCurrentSource(SourceBase, Protocol):  # PFClassId.CURRENT_SOURCE_AC
+    class AcCurrentSource(SourceBase, t.Protocol):  # PFClassId.CURRENT_SOURCE_AC
         Ir: float
         isetp: float
         cosini: float
@@ -1202,18 +1109,18 @@ class PowerFactoryTypes:
         B0: float
         phmc: PowerFactoryTypes.SourceTypeHarmonicCurrent | None
 
-    class Template(DataObject, Protocol):  # PFClassId.TEMPLATE
+    class Template(DataObject, t.Protocol):  # PFClassId.TEMPLATE
         ...
 
-    class CompoundModel(DataObject, Protocol):  # PFClassId.COMPOUND_MODEL
+    class CompoundModel(DataObject, t.Protocol):  # PFClassId.COMPOUND_MODEL
         ...
 
-    class DslModel(DataObject, Protocol):  # PFClassId.DSL_MODEL
+    class DslModel(DataObject, t.Protocol):  # PFClassId.DSL_MODEL
         ...
 
-    class Events(DataObject, Protocol): ...
+    class Events(DataObject, t.Protocol): ...
 
-    class Selection(DataObject, Protocol):  # PFClassId.SELECTION
+    class Selection(DataObject, t.Protocol):  # PFClassId.SELECTION
         iused: SelectionTarget
         iusedSub: SelectionType  # noqa: N815
 
@@ -1238,7 +1145,7 @@ class PowerFactoryTypes:
         def Clear(self) -> None:  # noqa: N802
             ...
 
-    class VariableMonitor(DataObject, Protocol):
+    class VariableMonitor(DataObject, t.Protocol):
         obj_id: PowerFactoryTypes.DataObject
 
         def AddVar(  # noqa: N802
@@ -1283,7 +1190,7 @@ class PowerFactoryTypes:
         def PrintVal(self) -> None:  # noqa: N802
             ...
 
-    class Result(DataObject, Protocol):  # PFClassId.RESULT
+    class Result(DataObject, t.Protocol):  # PFClassId.RESULT
         desc: Sequence[str]
         calTp: CalculationType  # noqa: N815
 
@@ -1369,7 +1276,7 @@ class PowerFactoryTypes:
             """Writes the current results (specified by VariableMonitor) to the result object."""
             ...
 
-    class Desktop(DataObject, Protocol):  # PFClassId.DESKTOP
+    class Desktop(DataObject, t.Protocol):  # PFClassId.DESKTOP
         def Close(self) -> bool:  # noqa: N802
             ...
 
@@ -1385,11 +1292,11 @@ class PowerFactoryTypes:
         def Unfreeze(self) -> bool:  # noqa: N802
             ...
 
-    class CommandBase(DataObject, Protocol):
+    class CommandBase(DataObject, t.Protocol):
         def Execute(self) -> int:  # noqa: N802
             ...
 
-    class CommandLoadFlow(CommandBase, Protocol):  # CalculationCommand.LOAD_FLOW
+    class CommandLoadFlow(CommandBase, t.Protocol):  # CalculationCommand.LOAD_FLOW
         iopt_net: NetworkExtendedCalcType
         iPST_at: bool  # noqa: N815  # automatic step control of phase shifting transformers
         iopt_plim: bool  # apply active power limits
@@ -1417,7 +1324,7 @@ class PowerFactoryTypes:
         def IsBalanced(self) -> int:  # noqa: N802
             ...
 
-    class CommandHarmonicCalculation(CommandBase, Protocol):  # CalculationCommand.HARMONIC_LOADFLOW
+    class CommandHarmonicCalculation(CommandBase, t.Protocol):  # CalculationCommand.HARMONIC_LOADFLOW
         iopt_sweep: int
         iopt_allfrq: int
         iopt_flicker: bool
@@ -1434,7 +1341,7 @@ class PowerFactoryTypes:
         ninc: float
         iopt_thd: int
 
-    class CommandFrequencySweep(CommandBase, Protocol):  # CalculationCommand.FREQUENCY_SWEEP
+    class CommandFrequencySweep(CommandBase, t.Protocol):  # CalculationCommand.FREQUENCY_SWEEP
         iopt_net: NetworkCalcType
         ildfinit: bool  # load flow initialisation
         fstart: float
@@ -1442,7 +1349,7 @@ class PowerFactoryTypes:
         fstop: float
         i_adapt: bool  # automatic step size adaption
 
-    class CommandSglLayout(CommandBase, Protocol):  # CalculationCommand.GRAPHIC_LAYOUT_TOOL
+    class CommandSglLayout(CommandBase, t.Protocol):  # CalculationCommand.GRAPHIC_LAYOUT_TOOL
         iAction: int  # noqa: N815
         orthoType: int  # noqa: N815
         insertionMode: int  # noqa: N815
@@ -1450,7 +1357,7 @@ class PowerFactoryTypes:
         neighborhoodSize: int  # noqa: N815
         neighborStartElems: PowerFactoryTypes.Selection  # noqa: N815
 
-    class CommandTimeSimulationStart(CommandBase, Protocol):  # CalculationCommand.TIME_DOMAIN_SIMULATION_START
+    class CommandTimeSimulationStart(CommandBase, t.Protocol):  # CalculationCommand.TIME_DOMAIN_SIMULATION_START
         iopt_sim: TimeSimulationType
         iopt_net: TimeSimulationNetworkCalcType
         iopt_show: int
@@ -1464,14 +1371,14 @@ class PowerFactoryTypes:
         dtemt: float  # step size electro-magnetic
         tstart: float  # start time related to 0 seconds
 
-    class CommandTimeSimulation(CommandBase, Protocol):  # CalculationCommand.TIME_DOMAIN_SIMULATION
+    class CommandTimeSimulation(CommandBase, t.Protocol):  # CalculationCommand.TIME_DOMAIN_SIMULATION
         tstop: float  # final simulation time
         cominc: PowerFactoryTypes.CommandTimeSimulationStart
 
         def GetSimulationTime(self) -> int:  # noqa: N802
             ...
 
-    class CommandResultExport(CommandBase, Protocol):  # CalculationCommand.RESULT_EXPORT
+    class CommandResultExport(CommandBase, t.Protocol):  # CalculationCommand.RESULT_EXPORT
         f_name: str  # only for specific ResultExportMode (2, 3, 4, 5, 6)
         ciopt_head: ResultExportColumnHeadingVariable
         col_Sep: str  # for csv: colunm separator  # noqa: N815
@@ -1484,7 +1391,7 @@ class PowerFactoryTypes:
         iopt_rscl: bool  # move time scale
         iopt_sep: bool  # True if system separator should be used
         iopt_tsel: bool  # use specific interval
-        iopt_vars: Literal[0, 1, 2]
+        iopt_vars: t.Literal[0, 1, 2]
         nsteps: int  # only when filtered is not 0
         numberFormat: ResultExportNumberFormat  # noqa: N815
         numberPrecisionFixed: int  # number of digits after decimal point  # noqa: N815
@@ -1495,7 +1402,7 @@ class PowerFactoryTypes:
         def ExportFullRange(self) -> None:  # noqa: N802
             ...
 
-    class Script(Protocol):
+    class Script(t.Protocol):
         def SetExternalObject(  # noqa: N802
             self,
             name: str,
@@ -1506,13 +1413,13 @@ class PowerFactoryTypes:
         def Execute(self) -> int:  # noqa: N802
             ...
 
-    class DplScript(Script, Protocol):  # PFClassId.SCRIPT_DPL
+    class DplScript(Script, t.Protocol):  # PFClassId.SCRIPT_DPL
         ...
 
-    class PythonScript(Script, Protocol):  # PFClassId.SCRIPT_PYTHON
+    class PythonScript(Script, t.Protocol):  # PFClassId.SCRIPT_PYTHON
         ...
 
-    class ProjectFolder(DataObject, Protocol):  # PFClassId.FOLDER
+    class ProjectFolder(DataObject, t.Protocol):  # PFClassId.FOLDER
         desc: Sequence[str]
         iopt_typ: FolderType
 
@@ -1522,7 +1429,7 @@ class PowerFactoryTypes:
         def IsProjectFolderType(self, folder_type: str) -> int:  # noqa: N802
             ...
 
-    class Application(Protocol):
+    class Application(t.Protocol):
         def ActivateProject(self, name: str) -> int:  # noqa: N802
             ...
 
@@ -1602,7 +1509,7 @@ class PowerFactoryTypes:
 
         def PostCommand(  # noqa: N802
             self,
-            command: Literal["exit"],
+            command: t.Literal["exit"],
             /,
         ) -> None: ...
 
@@ -1622,7 +1529,100 @@ class PowerFactoryTypes:
 
     class PowerFactoryExitError(Exception):
         code: int
-        args: tuple[Any, ...]
+        args: tuple[t.Any, ...]
+
+    ## The following may be part of version inconsistent behavior
+    class LoadTypeLV(DataObject, t.Protocol):  # PFClassId.LOAD_TYPE_LV
+        Smax: float  # maximum apparent power for a single residential unit, per default in kVA
+        cosphi: float  # power factor
+        ginf: float  # simultaneity factor
+
+        iLodTyp: PowerModelType  # composite (ZIP) / exponent  # noqa: N815
+        aP: float  # noqa: N815  # const. power part of the active power in relation to ZIP load model
+        bP: float  # noqa: N815  # const. current part of the active power in relation to ZIP load model
+        cP: float  # noqa: N815  # const. impedance part of the active power in relation to ZIP load model
+        aQ: float  # noqa: N815  # const. power part of the reactive power in relation to ZIP load model
+        bQ: float  # noqa: N815  # const. current part of the reactive power in relation to ZIP load model
+        cQ: float  # noqa: N815  # const. impedance part of the reactive power in relation to ZIP load model
+
+        eP: float  # noqa: N815  # exponent of the active power in relation to exponential load model
+        eQ: float  # noqa: N815  # exponent of the reactive power in relation to exponential load model
+
+    # LoadTypeMV is an equivalent of a distribution transformer
+    class LoadTypeMV(DataObject, t.Protocol):  # PFClassId.LOAD_TYPE_MV
+        strn: float  # rated power, per default in MVA
+        frnom: float  # nominal frequency
+        tratio: float  # transformer ratio
+        phtech: LoadPhaseConnectionType
+
+        uktr: float  # short-circuit voltage in percentage (pos. seq.)
+        pcutr: float  # cupper losses, per default in kW
+
+        iZzero: bool  # 1 zero seq. impedance is given; 0 zero seq. impedance is not given  # noqa: N815
+        uk0tr: float  # short-circuit voltage in percentage (zero. seq.)
+        ur0tr: float  # real part of uk0tr
+
+        pfe: float  # iron losses, per default in kW
+        dutap: float  # additional voltage per tap changer step in percentage
+        nntap0: int  # neutral position of tap changer
+        ntpmn: int  # lowest position of tap changer
+        ntpmx: int  # highest position of tap changer
+
+        LodTyp: PowerModelType  # composite (ZIP) / exponent
+        aP: float  # noqa: N815  # const. power part of the active power in relation to ZIP load model
+        bP: float  # noqa: N815  # const. current part of the active power in relation to ZIP load model
+        cP: float  # noqa: N815  # const. impedance part of the active power in relation to ZIP load model
+        aQ: float  # noqa: N815  # const. power part of the reactive power in relation to ZIP load model
+        bQ: float  # noqa: N815  # const. current part of the reactive power in relation to ZIP load model
+        cQ: float  # noqa: N815  # const. impedance part of the reactive power in relation to ZIP load model
+
+        eP: float  # noqa: N815  # exponent of the active power in relation to exponential load model
+        eQ: float  # noqa: N815  # exponent of the reactive power in relation to exponential load model
+
+    class LoadLVP(LoadBase, t.Protocol):  # PFClassId.LOAD_LV_PART
+        typ_id: PowerFactoryTypes.LoadTypeLV | None
+        iopt_inp: IOpt
+        elini: float
+        cplinia: float
+        slini: float
+        plini: float
+        qlini: float
+        ilini: float
+        coslini: float
+        ulini: float
+        pnight: float
+        cSav: float  # noqa: N815
+        cSmax: float  # noqa: N815
+        ccosphi: float
+        phtech: LoadLVPhaseConnectionType
+
+    class LoadLV(LoadBase3Ph, LoadLVP, t.Protocol):  # PFClassId.LOAD_LV
+        typ_id: PowerFactoryTypes.LoadTypeLV | None
+        i_sym: ISym
+        lodparts: Sequence[PowerFactoryTypes.LoadLVP]
+        phtech: LoadLVPhaseConnectionType
+
+    class LoadMV(LoadBase3Ph, t.Protocol):  # PFClassId.LOAD_MV
+        typ_id: PowerFactoryTypes.LoadTypeMV | None
+        mode_inp: ModeInpMV
+        ci_sym: ISym
+        elini: float
+        cplinia: float
+        sgini: float
+        sginir: float
+        sginis: float
+        sginit: float
+        pgini: float
+        pginir: float
+        pginis: float
+        pginit: float
+        cosgini: float
+        cosginir: float
+        cosginis: float
+        cosginit: float
+        gscale: float
+        pfg_recap: PFRecap
+        phtech: LoadPhaseConnectionType
 
 
 ValidPFPrimitive = PowerFactoryTypes.DataObject | str | bool | int | float | None
diff --git a/pyproject.toml b/pyproject.toml
index 83e2dec..aa15b51 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -40,56 +40,53 @@
 
 [tool.ruff]
   line-length = 120
-  
-[tool.ruff.lint]
-  ignore = [
-    "ANN002",
-    "ANN003",
-    "ANN101",
-    "ANN102",
-    "C901",
-    "D100",
-    "D101",
-    "D102",
-    "D103",
-    "D104",
-    "D105",
-    "D106",
-    "D107",
-    "D202",
-    "D203",
-    "D401",
-    "E402",
-    "E501",
-  ]
-  select = ["ALL"]
 
-  [tool.ruff.lint.flake8-type-checking]
-    runtime-evaluated-decorators = ["pydantic.dataclasses.dataclass"]
+  [tool.ruff.lint]
+    ignore = [
+      "ANN002",
+      "ANN003",
+      "ANN101",
+      "ANN102",
+      "C901",
+      "D100",
+      "D101",
+      "D102",
+      "D103",
+      "D104",
+      "D105",
+      "D106",
+      "D107",
+      "D202",
+      "D203",
+      "D401",
+      "E402",
+      "E501",
+    ]
+    select = ["ALL"]
+
+    [tool.ruff.lint.flake8-type-checking]
+      runtime-evaluated-decorators = ["pydantic.dataclasses.dataclass"]
 
-  [tool.ruff.lint.isort]
-    force-single-line = true
+    [tool.ruff.lint.isort]
+      force-single-line = true
 
-  [tool.ruff.lint.pydocstyle]
-    convention = "pep257"
+    [tool.ruff.lint.pydocstyle]
+      convention = "pep257"
 
-  [tool.ruff.lint.pep8-naming]
-    classmethod-decorators = [
-      "classmethod",
-      "pydantic.root_validator",
-      "pydantic.validator",
-    ]
+    [tool.ruff.lint.pep8-naming]
+      classmethod-decorators = ["classmethod", "pydantic.field_validator"]
 
-  [tool.ruff.lint.pylint]
-    max-args = 10
+    [tool.ruff.lint.pylint]
+      max-args = 10
 
-  [tool.ruff.lint.flake8-import-conventions.extend-aliases]
-    "datetime"         = "dt"
-    "geopandas"        = "gpd"
-    "numpy.typing"     = "npt"
-    "rasterio"         = "rio"
-    "shapely.geometry" = "shg"
-    "typing"           = "t"
+    [tool.ruff.lint.flake8-import-conventions.extend-aliases]
+      "collections.abc"  = "cabc"
+      "datetime"         = "dt"
+      "geopandas"        = "gpd"
+      "numpy.typing"     = "npt"
+      "rasterio"         = "rio"
+      "shapely.geometry" = "shg"
+      "typing"           = "t"
 
 [tool.ruff.lint.per-file-ignores]
   "tests/*" = ["ANN001", "ANN201", "INP001", "S101"]
@@ -104,8 +101,8 @@
   version_files = [
     ".zenodo.json:version",
     "CITATION.cff:cff-version",
+    "powerfactory_tools/__version__.py:VERSION",
     "pyproject.toml:version",
-    "powerfactory_tools/interface.py:VERSION",
   ]
 
 [tool.mypy]


Test patch:
diff --git a/tests/test_interface.py b/tests/test_interface.py
index eab3794..09064d2 100644
--- a/tests/test_interface.py
+++ b/tests/test_interface.py
@@ -1,6 +1,6 @@
 import logging
 
-from powerfactory_tools import PowerFactoryInterface
+from powerfactory_tools.versions.pf2022 import PowerFactoryInterface
 
 
 class TestInterface: