You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by bo...@apache.org on 2022/11/12 15:01:29 UTC

[incubator-streampipes] 14/18: tmp

This is an automated email from the ASF dual-hosted git repository.

bossenti pushed a commit to branch feature/STREAMPIPES-607
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git

commit 37c67d01574e84b6feb5ffe330ab1e5237f11d01
Author: bossenti <bo...@posteo.de>
AuthorDate: Fri Nov 11 21:40:01 2022 +0100

    tmp
---
 streampipes-client-python/.pre-commit-config.yaml  | 31 +++++-----
 .../{README.md => DEVELOPMENT.md}                  | 48 +++++----------
 streampipes-client-python/Makefile                 |  2 +-
 streampipes-client-python/README.md                | 24 +-------
 streampipes-client-python/setup.py                 | 10 +---
 .../streampipes_client/__init__.py                 |  6 +-
 .../streampipes_client/__version__.py              |  4 ++
 .../streampipes_client/client/__init__.py          |  6 +-
 .../streampipes_client/client/client.py            | 40 ++++++-------
 .../streampipes_client/client/credentials.py       | 22 +++----
 .../client/{ => endpoint}/__init__.py              |  9 ++-
 .../{ => client}/endpoint/data_lake_measure.py     |  3 +-
 .../streampipes_client/client/endpoint/endpoint.py | 68 ++++++++++++++++------
 .../streampipes_client/endpoint/__init__.py        | 16 -----
 .../streampipes_client/model/__init__.py           |  2 +-
 .../streampipes_client/model/common.py             | 24 ++++----
 .../model/container/data_lake_measures.py          |  4 +-
 .../model/container/model_container.py             | 10 +---
 .../streampipes_client/model/element/__init__.py   |  2 +-
 .../model/element/data_lake_measure.py             |  3 +-
 20 files changed, 159 insertions(+), 175 deletions(-)

diff --git a/streampipes-client-python/.pre-commit-config.yaml b/streampipes-client-python/.pre-commit-config.yaml
index c876c23f3..334a07141 100644
--- a/streampipes-client-python/.pre-commit-config.yaml
+++ b/streampipes-client-python/.pre-commit-config.yaml
@@ -14,8 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-
-files: streampipes_client, tests
+files: streampipes_client/|tests/
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
     rev: v4.2.0
@@ -28,32 +27,38 @@ repos:
 
   - repo: local
     hooks:
+      - id: pyupgrade
+        name: pyupgrade
+        language: python
+        types: [ python ]
+        entry: pyupgrade --py38-plus --keep-runtime-typing
+        require_serial: true
+
       - id: black
         name: black
         language: python
         types: [python]
-        entry: black
+        entry: black --line-length=120
+        require_serial: true
 
       - id: isort
         name: isort
         language: python
         types: [python]
-        entry: isort
+        entry: isort --profile black
+        require_serial: true
+        verbose: true
 
-      - id: ruff
-        name: ruff
+      - id: flake8
+        name: flake8
         language: python
         types: [python]
-        entry: ruff
+        entry: flake8 --max-line-length 120
+        require_serial: true
 
       - id: mypy
         name: mypy
         language: python
         types: [python]
         entry: mypy
-
-      - id: pyupgrade
-        name: pyupgrade
-        language: python
-        types: [python]
-        entry: pyupgrade --py38-plus --keep-runtime-typing
\ No newline at end of file
+        require_serial: true
\ No newline at end of file
diff --git a/streampipes-client-python/README.md b/streampipes-client-python/DEVELOPMENT.md
similarity index 52%
copy from streampipes-client-python/README.md
copy to streampipes-client-python/DEVELOPMENT.md
index c4164d196..27bb7d1f3 100644
--- a/streampipes-client-python/README.md
+++ b/streampipes-client-python/DEVELOPMENT.md
@@ -16,38 +16,13 @@
   ~
 -->
 
-# StreamPipes client for Python
+# Development Guide
+This document describes how to easily set up your local dev environment to develop on the
+StreamPipes Python client :snake:
 
-Apache StreamPipes meets Python! We are working highly motivated on a Python-based client to interact with StreamPipes.
-In this way, we would like to unite the power of StreamPipes to easily connect to and read different data sources, especially in the IoT domain,
-and the amazing universe of data analytics libraries in Python.
+### First Steps :rocket:
 
-<h1 align="center">
-  <br>
-   <img src="./docs/img/streampipes-python.png" 
-   alt="StreamPipes Logo with Python" title="Apache StreamPipes Logo with Python" width="75%"/>
-  <br>
-</h1>
-
-<br>
-
-**:exclamation::exclamation::exclamation:IMPORTANT:exclamation::exclamation::exclamation:**
-<br>
-<br>
-**The current version of this Python client is still in alpha phase at best**
-<br>
-**This means that it is still heavily under development, which may result in frequent and extensive API changes, unstable behavior, etc.**
-<br>
-**Please consider it only as paa sneak preview.**
-<br>
-<br>
-**:exclamation::exclamation::exclamation:IMPORTANT:exclamation::exclamation::exclamation:**
-
-<br>
-
-### Get ready for development
-
-1) Set up your Python environment
+1) **Set up your Python environment**
 <br>
 Create a virtual Python environment with a tool of your choice, here are some examples.
 As a next step, install all required dependencies for the development, e.g. with pip:
@@ -56,7 +31,8 @@ As a next step, install all required dependencies for the development, e.g. with
 pip install .[dev]  # or alternatively: pip install .[docs]
 ```
 <br>
-2) Install pre-commit hook
+
+2) **Install pre-commit hook**
 <br>
 The pre-commit hook is run before every commit and takes care about code style,
 linting, type hints, import sorting, etc.
@@ -65,4 +41,12 @@ Ensure to have the recent version of the pre-commit installed otherwise the CI b
 ```
 pre-commit install
 ```
-The definition of the pre-commit hook can found in [.pre-commit-config.yaml](.pre-commit-config.yaml).
\ No newline at end of file
+The definition of the pre-commit hook can be found in [.pre-commit-config.yaml](.pre-commit-config.yaml).
+
+### Conventions :clap:
+Below we list some conventions that we have agreed on for creating the StreamPipes Python client.
+Please follow them when you plan to contribute to this project.
+If you have any other suggestions or would like to discuss them, we would be happy to hear from you on our mailing list [dev@streampipes.apache.org](mailto:dev@streampipes.apache.org).
+
+1) **Use `numpy` style for Python docstrings** :page_facing_up: <br>
+Please stick to the `numpy` style when writing docstrings, as we require this for generating our documentation.
diff --git a/streampipes-client-python/Makefile b/streampipes-client-python/Makefile
index 309ad627f..55a203d71 100644
--- a/streampipes-client-python/Makefile
+++ b/streampipes-client-python/Makefile
@@ -27,4 +27,4 @@ livedoc: doc
 	mkdocs serve --dirtyreload
 
 rebase:
-	git fetch && git rebase origin/dev
\ No newline at end of file
+	git fetch && git rebase origin/dev
diff --git a/streampipes-client-python/README.md b/streampipes-client-python/README.md
index c4164d196..8cad0839d 100644
--- a/streampipes-client-python/README.md
+++ b/streampipes-client-python/README.md
@@ -24,7 +24,7 @@ and the amazing universe of data analytics libraries in Python.
 
 <h1 align="center">
   <br>
-   <img src="./docs/img/streampipes-python.png" 
+   <img src="./docs/img/streampipes-python.png"
    alt="StreamPipes Logo with Python" title="Apache StreamPipes Logo with Python" width="75%"/>
   <br>
 </h1>
@@ -44,25 +44,3 @@ and the amazing universe of data analytics libraries in Python.
 **:exclamation::exclamation::exclamation:IMPORTANT:exclamation::exclamation::exclamation:**
 
 <br>
-
-### Get ready for development
-
-1) Set up your Python environment
-<br>
-Create a virtual Python environment with a tool of your choice, here are some examples.
-As a next step, install all required dependencies for the development, e.g. with pip:
-
-```
-pip install .[dev]  # or alternatively: pip install .[docs]
-```
-<br>
-2) Install pre-commit hook
-<br>
-The pre-commit hook is run before every commit and takes care about code style,
-linting, type hints, import sorting, etc.
-Ensure to have the recent version of the pre-commit installed otherwise the CI build might fail:
-
-```
-pre-commit install
-```
-The definition of the pre-commit hook can found in [.pre-commit-config.yaml](.pre-commit-config.yaml).
\ No newline at end of file
diff --git a/streampipes-client-python/setup.py b/streampipes-client-python/setup.py
index 4914564f8..9cc3766d1 100644
--- a/streampipes-client-python/setup.py
+++ b/streampipes-client-python/setup.py
@@ -30,23 +30,19 @@ AUTHOR = "Apache Software Foundation"
 REQUIRES_PYTHON = ">=3.8.0"
 
 # Package requirements.
-base_packages = [
-    "pandas>=1.5.1",
-    "pydantic>=1.10.2",
-    "requests>=2.28.1"
-]
+base_packages = ["pandas>=1.5.1", "pydantic>=1.10.2", "requests>=2.28.1"]
 
 dev_packages = base_packages + [
     "mypy>=0.990",
-    "pre-commit>=2.20.0",
     "pytest>=7.2.0",
     "pytest-cov>=4.0.0",
     "black>=22.10.0",
     "flake8>=5.0.4",
     "isort>=5.10.1",
+    "pyupgrade>=3.2.2"
 ]
 
-docs_packages = [ #todo Cedric check versions
+docs_packages = [
     "mkdocs>=1.2.3",
     "mkdocs-material>=8.1.11",
     "mkdocstrings[python]>=0.19.0",
diff --git a/streampipes-client-python/streampipes_client/__init__.py b/streampipes-client-python/streampipes_client/__init__.py
index ecb1860df..7bb805d49 100644
--- a/streampipes-client-python/streampipes_client/__init__.py
+++ b/streampipes-client-python/streampipes_client/__init__.py
@@ -13,4 +13,8 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
\ No newline at end of file
+#
+
+"""
+This library provides a handy Python-based client to interact with Apache StreamPipes.
+"""
diff --git a/streampipes-client-python/streampipes_client/__version__.py b/streampipes-client-python/streampipes_client/__version__.py
index 492084802..819a48a81 100644
--- a/streampipes-client-python/streampipes_client/__version__.py
+++ b/streampipes-client-python/streampipes_client/__version__.py
@@ -15,6 +15,10 @@
 # limitations under the License.
 #
 
+"""
+Storing the current version number, predominantly used by `setup.py`.
+"""
+
 VERSION = (0, 71, 0)
 
 __version__ = ".".join(map(str, VERSION))  # noqa: F401
diff --git a/streampipes-client-python/streampipes_client/client/__init__.py b/streampipes-client-python/streampipes_client/client/__init__.py
index a323247a5..47db35729 100644
--- a/streampipes-client-python/streampipes_client/client/__init__.py
+++ b/streampipes-client-python/streampipes_client/client/__init__.py
@@ -15,5 +15,9 @@
 # limitations under the License.
 #
 
-from .client import StreamPipesClient
+"""
+This module contains everything about the client itself, the central point of interaction with StreamPipes.
+"""
+
+from .client import StreamPipesClient, StreamPipesClientConfig
 from .credentials import StreamPipesApiKeyCredentials
diff --git a/streampipes-client-python/streampipes_client/client/client.py b/streampipes-client-python/streampipes_client/client/client.py
index f7948b7c0..51323d947 100644
--- a/streampipes-client-python/streampipes_client/client/client.py
+++ b/streampipes-client-python/streampipes_client/client/client.py
@@ -20,18 +20,15 @@ from dataclasses import dataclass
 from typing import Dict, Optional
 
 import requests
-
 from streampipes_client.client.credentials import CredentialProvider
-from streampipesclient.endpoints import DataLakeMeasureEndpoint
+from streampipes_client.client.endpoint import DataLakeMeasureEndpoint
 
 logger = logging.getLogger(__name__)
 
 
 @dataclass
 class StreamPipesClientConfig:
-    """
-
-    """
+    """ """
 
     credential_provider: CredentialProvider
     host_address: str
@@ -40,12 +37,12 @@ class StreamPipesClientConfig:
 
 
 class StreamPipesClient:
-
-    def __init__(self,
-                 *,
-                 client_config: StreamPipesClientConfig,
-                 logging_level: int = logging.INFO,
-                 ):
+    def __init__(
+        self,
+        *,
+        client_config: StreamPipesClientConfig,
+        logging_level: int = logging.INFO,
+    ):
         self.client_config = client_config
 
         self.request_session = requests.Session()
@@ -67,19 +64,22 @@ class StreamPipesClient:
         logger.info(f"Logging successfully initialized with logging level {logging.getLevelName(logging_level)}.")
 
     @classmethod
-    def create(cls, *, client_config: StreamPipesClientConfig, logging_level: int = logging.INFO):
+    def create(
+        cls,
+        *,
+        client_config: StreamPipesClientConfig,
+        logging_level: int = logging.INFO,
+    ):
         return cls(client_config=client_config, logging_level=logging_level)
 
     @property
     def http_headers(self) -> Dict[str, str]:
-        return self.client_config.credential_provider.make_headers(
-            {
-                "Application": "application/json"
-            }
-        )
+        return self.client_config.credential_provider.make_headers({"Application": "application/json"})
 
     @property
     def base_api_path(self) -> str:
-        return f"{'http://' if self.client_config.https_disabled else 'https://'}" \
-               f"{self.client_config.host_address}:" \
-               f"{self.client_config.port}/streampipes-backend/"
+        return (
+            f"{'http://' if self.client_config.https_disabled else 'https://'}"
+            f"{self.client_config.host_address}:"
+            f"{self.client_config.port}/streampipes-backend/"
+        )
diff --git a/streampipes-client-python/streampipes_client/client/credentials.py b/streampipes-client-python/streampipes_client/client/credentials.py
index fe2cc2b89..de60cb95b 100644
--- a/streampipes-client-python/streampipes_client/client/credentials.py
+++ b/streampipes-client-python/streampipes_client/client/credentials.py
@@ -19,32 +19,26 @@ from typing import Dict, Optional
 
 
 class CredentialProvider(ABC):
-
     @abstractmethod
     def make_headers(self, http_headers: Optional[Dict[str, str]] = None) -> Dict[str, str]:
         raise NotImplementedError
 
 
 class StreamPipesApiKeyCredentials(CredentialProvider):
-
-    def __init__(self,
-                 *,
-                 username: str,
-                 api_key: str,
-                 ):
+    def __init__(
+        self,
+        *,
+        username: str,
+        api_key: str,
+    ):
         self.username = username
         self.api_key = api_key
 
-    def make_headers(self,  http_headers: Optional[Dict[str, str]] = None) -> Dict[str, str]:
+    def make_headers(self, http_headers: Optional[Dict[str, str]] = None) -> Dict[str, str]:
 
         if http_headers is None:
             http_headers = {}
 
-        http_headers.update(
-            {
-                "X-API-User": self.username,
-                "X-API-Key": self.api_key
-            }
-        )
+        http_headers.update({"X-API-User": self.username, "X-API-Key": self.api_key})
 
         return http_headers
diff --git a/streampipes-client-python/streampipes_client/client/__init__.py b/streampipes-client-python/streampipes_client/client/endpoint/__init__.py
similarity index 70%
copy from streampipes-client-python/streampipes_client/client/__init__.py
copy to streampipes-client-python/streampipes_client/client/endpoint/__init__.py
index a323247a5..75f4dca5d 100644
--- a/streampipes-client-python/streampipes_client/client/__init__.py
+++ b/streampipes-client-python/streampipes_client/client/endpoint/__init__.py
@@ -14,6 +14,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+"""
+This module contains the implementation of all endpoints of the StreamPipes client.
+One endpoint aims to handle the whole interaction with a central endpoint of the StreamPipes API.
+"""
+from .data_lake_measure import DataLakeMeasureEndpoint
+from .endpoint import APIEndpoint
 
-from .client import StreamPipesClient
-from .credentials import StreamPipesApiKeyCredentials
+__all__ = ["APIEndpoint", "DataLakeMeasureEndpoint"]
diff --git a/streampipes-client-python/streampipes_client/endpoint/data_lake_measure.py b/streampipes-client-python/streampipes_client/client/endpoint/data_lake_measure.py
similarity index 83%
rename from streampipes-client-python/streampipes_client/endpoint/data_lake_measure.py
rename to streampipes-client-python/streampipes_client/client/endpoint/data_lake_measure.py
index 6ee4c8403..76f5a1c2a 100644
--- a/streampipes-client-python/streampipes_client/endpoint/data_lake_measure.py
+++ b/streampipes-client-python/streampipes_client/client/endpoint/data_lake_measure.py
@@ -1,9 +1,8 @@
-from streampipes_client.endpoint.endpoint import APIEndpoint
+from client.endpoint.endpoint import APIEndpoint
 from streampipes_client.model.container.data_lake_measures import DataLakeMeasures
 
 
 class DataLakeMeasureEndpoint(APIEndpoint):
-
     @classmethod
     def _container_cls(cls):
         return DataLakeMeasures
diff --git a/streampipes-client-python/streampipes_client/client/endpoint/endpoint.py b/streampipes-client-python/streampipes_client/client/endpoint/endpoint.py
index 9bf2f1984..8547c69bf 100644
--- a/streampipes-client-python/streampipes_client/client/endpoint/endpoint.py
+++ b/streampipes-client-python/streampipes_client/client/endpoint/endpoint.py
@@ -21,37 +21,52 @@ Provided classes and assets are aimed to be used for developing endpoints.
 An endpoint is provides all options to communicate with a central endpoint of the StreamPipes API in a handy way.
 """
 
-from http import HTTPStatus
 import logging
 from abc import ABC, abstractmethod
-from typing import Tuple, Type, Callable
+from http import HTTPStatus
+from typing import Callable, Tuple, Type
 
 from requests import Response
-from requests.exceptions import HTTPError
-
+from requests.exceptions import BaseHTTPError, HTTPError
 from streampipes_client.model.container import ModelContainer
 from streampipes_client.model.element import Element
 
+__all__ = ["APIEndpoint"]
+
 logger = logging.getLogger(__name__)
 
 
 # define custom logging messages for some specific HTTP status
 status_code_to_log_message = {
     401: "\nThe StreamPipes Backend returned an unauthorized error.\n"
-         "Please check your user name and/or password to be correct.",
-    403: "\nThere seems to be an issue with the access rights of the given user and the ressource you queried.\n"
-         "Apparently, this user is not allowed to query the resource.\n"
-         "Please check the user's permissions or contact your StreamPipes admin.",
+    "Please check your user name and/or password to be correct.",
+    403: "\nThere seems to be an issue with the access rights of the given user and the resource you queried.\n"
+    "Apparently, this user is not allowed to query the resource.\n"
+    "Please check the user's permissions or contact your StreamPipes admin.",
     **dict.fromkeys(
         [404, 405],
         "\nOops, there seems to be an issue with the Python Client calling the API inappropriately.\n"
         "This should not happen, but unfortunately did.\n"
-        "If you don't mind, it would be awesome to let us know by creating an issue at github.com/apache/incubator-streampipes.\n"
-        "Please paste the following information to the issue description:\n\n")
+        "If you don't mind, it would be awesome to let us know by creating an issue"
+        " at github.com/apache/incubator-streampipes.\n"
+        "Please paste the following information to the issue description:\n\n",
+    ),
 }
 
 
 class APIEndpoint(ABC):
+    """Abstract implementation of an API endpoint.
+    Serves as template for all endpoints for the StreamPipes API.
+    By design, endpoints are only instantiated within the `__init__` method of the StreamPipesClient.
+
+    Could be extended by additional subtypes in the future.
+
+    Parameters
+    ----------
+    parent_client: `client.StreamPipesClient`
+        This parameter expects the instance of the `StreamPipesClient` the endpoint is attached to.
+
+    """
 
     def __init__(self, parent_client: "StreamPipesClient"):
         self._parent_client = parent_client
@@ -59,18 +74,34 @@ class APIEndpoint(ABC):
     @property
     @abstractmethod
     def _relative_api_path(self) -> Tuple[str]:
+        """
+        Defines the relative api path with regard to the StreamPipes API URL.
+        Each path within the URL is defined as an own string.
+
+        Returns
+        -------
+            A tuple of strings of which every represents a path value of the endpoint's API URL.
+
+        """
         raise NotImplementedError
 
     @classmethod
     @abstractmethod
     def _container_cls(cls) -> Type[ModelContainer]:
+        """
+
+        Returns
+        -------
+            A class which inherits from `model.ModelContainer`
+        """
         raise NotImplementedError
 
-    def _make_request(self,
-                      *,
-                      request_method: Callable[..., Response],
-                      url: str,
-                      ) -> Response:
+    def _make_request(
+        self,
+        *,
+        request_method: Callable[..., Response],
+        url: str,
+    ) -> Response:
 
         response = request_method(url=url)
 
@@ -82,7 +113,10 @@ class APIEndpoint(ABC):
 
             log_message = status_code_to_log_message[err.response.status_code]
 
-            if status_code in [HTTPStatus.METHOD_NOT_ALLOWED.numerator, HTTPStatus.NOT_FOUND.numerator]:
+            if status_code in [
+                HTTPStatus.METHOD_NOT_ALLOWED.numerator,
+                HTTPStatus.NOT_FOUND.numerator,
+            ]:
                 log_message += f"url: {err.response.url}\nstatus code: {err.response.status_code}"
 
             logger.debug(err.response.text)
@@ -101,7 +135,7 @@ class APIEndpoint(ABC):
 
         response = self._make_request(
             request_method=self._parent_client.request_session.get,
-            url=self.create_api_path()
+            url=self.create_api_path(),
         )
         return self._container_cls().from_json(json_string=response.text)
 
diff --git a/streampipes-client-python/streampipes_client/endpoint/__init__.py b/streampipes-client-python/streampipes_client/endpoint/__init__.py
deleted file mode 100644
index ecb1860df..000000000
--- a/streampipes-client-python/streampipes_client/endpoint/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
\ No newline at end of file
diff --git a/streampipes-client-python/streampipes_client/model/__init__.py b/streampipes-client-python/streampipes_client/model/__init__.py
index ecb1860df..cce3acad3 100644
--- a/streampipes-client-python/streampipes_client/model/__init__.py
+++ b/streampipes-client-python/streampipes_client/model/__init__.py
@@ -13,4 +13,4 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
\ No newline at end of file
+#
diff --git a/streampipes-client-python/streampipes_client/model/common.py b/streampipes-client-python/streampipes_client/model/common.py
index b1994372f..4c78c906c 100644
--- a/streampipes-client-python/streampipes_client/model/common.py
+++ b/streampipes-client-python/streampipes_client/model/common.py
@@ -17,7 +17,7 @@
 
 from typing import List, Optional
 
-from pydantic import BaseModel, StrictStr, StrictInt, StrictBool, ValidationError
+from pydantic import BaseModel, StrictBool, StrictInt, StrictStr, ValidationError
 
 
 def snake_to_camel_case(snake_case_string: str) -> str:
@@ -67,19 +67,21 @@ class EventSchema(BasicModel):
 
 
 class StreamPipesDataModelError(RuntimeError):
-
     def __init__(self, validation_error: ValidationError):
         super().__init__(
-            self._generate_error_message(model=validation_error.model,
-                                         error_description=validation_error.json(),
-                                         )
+            self._generate_error_message(
+                model=validation_error.model,
+                error_description=validation_error.json(),
+            )
         )
 
     @staticmethod
     def _generate_error_message(*, model: BasicModel, error_description: str) -> str:
-        return f"\nOops, there seems to be a problem with our internal StreamPipes data model.\n" \
-               f"This should not occur, but unfortunately did.\n" \
-               f"Therefore, it would be great if you could report this problem as an issue at github.com/apache/incubator-streampipes.\n" \
-               f"Please don't forget to include the following information:\n\n" \
-               f"Affected Model class: {str(model)}\n" \
-               f"Validation error log: {error_description}"
+        return (
+            f"\nOops, there seems to be a problem with our internal StreamPipes data model.\n"
+            f"This should not occur, but unfortunately did.\n"
+            f"Therefore, it would be great if you could report this problem as an issue at github.com/apache/incubator-streampipes.\n"
+            f"Please don't forget to include the following information:\n\n"
+            f"Affected Model class: {str(model)}\n"
+            f"Validation error log: {error_description}"
+        )
diff --git a/streampipes-client-python/streampipes_client/model/container/data_lake_measures.py b/streampipes-client-python/streampipes_client/model/container/data_lake_measures.py
index 758a57a8b..9f36cf86b 100644
--- a/streampipes-client-python/streampipes_client/model/container/data_lake_measures.py
+++ b/streampipes-client-python/streampipes_client/model/container/data_lake_measures.py
@@ -1,14 +1,12 @@
 import pandas as pd
-
 from streampipes_client.model.container import ModelContainer
 from streampipes_client.model.element.data_lake_measure import DataLakeMeasure
 
 
 class DataLakeMeasures(ModelContainer):
-
     @classmethod
     def _element_cls(cls):
         return DataLakeMeasure
 
     def to_pandas(self) -> pd.DataFrame:
-        pass
\ No newline at end of file
+        pass
diff --git a/streampipes-client-python/streampipes_client/model/container/model_container.py b/streampipes-client-python/streampipes_client/model/container/model_container.py
index 072e590ff..596545404 100644
--- a/streampipes-client-python/streampipes_client/model/container/model_container.py
+++ b/streampipes-client-python/streampipes_client/model/container/model_container.py
@@ -15,20 +15,16 @@
 # limitations under the License.
 #
 import json
-
-import pandas as pd
-
 from abc import ABC, abstractmethod
 from typing import List, Type
 
+import pandas as pd
 from pydantic import ValidationError
-
 from streampipes_client.model.common import StreamPipesDataModelError
 from streampipes_client.model.element import Element
 
 
 class ModelContainer(ABC):
-
     def __init__(self, elements: List[Element]):
         self._elements = elements
 
@@ -48,9 +44,7 @@ class ModelContainer(ABC):
 
         try:
 
-            model_container = cls(
-                elements=[cls._element_cls().parse_obj(list_item) for list_item in data]
-            )
+            model_container = cls(elements=[cls._element_cls().parse_obj(list_item) for list_item in data])
         except ValidationError as ve:
             raise StreamPipesDataModelError(validation_error=ve)
 
diff --git a/streampipes-client-python/streampipes_client/model/element/__init__.py b/streampipes-client-python/streampipes_client/model/element/__init__.py
index f4b8a3ece..a8f3b03aa 100644
--- a/streampipes-client-python/streampipes_client/model/element/__init__.py
+++ b/streampipes-client-python/streampipes_client/model/element/__init__.py
@@ -15,4 +15,4 @@
 # limitations under the License.
 #
 
-from .element import Element
\ No newline at end of file
+from .element import Element
diff --git a/streampipes-client-python/streampipes_client/model/element/data_lake_measure.py b/streampipes-client-python/streampipes_client/model/element/data_lake_measure.py
index 444978d3e..ca5a89fd9 100644
--- a/streampipes-client-python/streampipes_client/model/element/data_lake_measure.py
+++ b/streampipes-client-python/streampipes_client/model/element/data_lake_measure.py
@@ -16,8 +16,7 @@
 #
 from typing import Optional
 
-from pydantic import StrictStr, StrictBool
-
+from pydantic import StrictBool, StrictStr
 from streampipes_client.model.common import EventSchema
 from streampipes_client.model.element import Element