You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2020/02/26 11:10:03 UTC

[plc4x] branch develop updated: Refactor PlcDriverManager as context manager

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

cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new 7b556a1  Refactor PlcDriverManager as context manager
     new 44f0ebc  Merge pull request #124 from nuclearpinguin/feature/plc4py
7b556a1 is described below

commit 7b556a12ee18daa7d06e90327c212fe773b666a7
Author: Tomek Urbaszek <to...@polidea.com>
AuthorDate: Sun Feb 23 12:49:29 2020 +0100

    Refactor PlcDriverManager as context manager
---
 .gitignore                                         |  1 +
 sandbox/plc4py/README.md                           | 23 ++-----
 .../python/org/apache/plc4x/PlcDriverManager.py    | 74 +++++++++++++++-------
 3 files changed, 55 insertions(+), 43 deletions(-)

diff --git a/.gitignore b/.gitignore
index 282586c..6691622 100644
--- a/.gitignore
+++ b/.gitignore
@@ -96,6 +96,7 @@ plc4cpp/cmake-build-debug/
 plc4py/venv/
 **/__pycache__/**/*
 /plc4cpp/.vscode/ipch
+*.egg-info
 
 # Exclude gradle stuff
 .gradle
diff --git a/sandbox/plc4py/README.md b/sandbox/plc4py/README.md
index 41f5545..05bf569 100644
--- a/sandbox/plc4py/README.md
+++ b/sandbox/plc4py/README.md
@@ -30,29 +30,14 @@ Some tests can be found in `test/test_PlcDriverManager.py`.
 Here is some example code:
 
 ```python
-try:
-    manager = PlcDriverManager()
-
-    connection = None
-    try:
-        connection = manager.get_connection("s7://192.168.167.210/0/1")
+with PlcDriverManager() as manager:
+    with manager.connection("s7://192.168.167.210/0/1") as conn:
         for _ in range(100):
-            result = connection.execute(Request(fields={"field1": "%M0:USINT"}))
+            result = conn.execute(Request(fields={"field1": "%M0:USINT"}))
             print("Response Code is " + str(result.get_field("field1").get_response_code()))
-            # We now that we want to get an int...
+            # We know that we want to get an int...
             print("Response Value is " + str(result.get_field("field1").get_int_value()))
-
-    except PlcException as e:
-        raise Exception(str(e.url))
-    finally:
-        if connection is not None:
-            connection.close()
-finally:
-    manager.close()
 ```
 
-the `PlcDriverManager` spawns an interop server in the background, thus it is important to close it afterwards.
-Otherwise this process keeps alive and you have to kill by yourself.
-
 All generated files (from thrift) are in `org.apache.plc4x.interop`.
 I built a very simple Python API in `org.apache.plc4x`.
diff --git a/sandbox/plc4py/src/main/python/org/apache/plc4x/PlcDriverManager.py b/sandbox/plc4py/src/main/python/org/apache/plc4x/PlcDriverManager.py
index aa68418..f818bdf 100644
--- a/sandbox/plc4py/src/main/python/org/apache/plc4x/PlcDriverManager.py
+++ b/sandbox/plc4py/src/main/python/org/apache/plc4x/PlcDriverManager.py
@@ -18,6 +18,7 @@
 import subprocess
 import time
 import warnings
+from contextlib import contextmanager
 
 from generated.org.apache.plc4x.interop.InteropServer import Client, PlcException
 from thrift.protocol import TBinaryProtocol
@@ -28,41 +29,44 @@ from org.apache.plc4x.PlcConnection import PlcConnection
 
 
 class PlcDriverManager:
-
     """
-    constructor, initialize the server
+    Constructor, initialize the server
     """
     def __init__(self, embedded_server=True):
         self.embedded_server = embedded_server
+        self.interop_proc = None
         # Start the Server in the background
         if embedded_server:
-            self.interop_proc = subprocess.Popen(
-                ["java", "-Dlog4j.configurationFile=../lib/log4j2.xml",
-                 "-jar", "../lib/interop-server.jar"])
-            try:
-                print("Started server under pid " + str(self.interop_proc.pid))
-            except:
-                print("Encountered an Exception while starting Interop Server")
-                raise PlcException("Unable to start the Interop Server!")
+            self.start_server()
 
-            time.sleep(2)
-            poll = self.interop_proc.poll()
-            if poll is None:
-                print("Sucesfully started the Interop Server...")
-            else:
-                warnings.warn("Interop Server died after starting up...")
-                raise PlcException(
-                    "Unable to start the Interop Server. Is another Server still running under the same port?")
+        transport = TSocket.TSocket('localhost', 9090)
+        self.transport = TTransport.TBufferedTransport(transport)
+        self.protocol = TBinaryProtocol.TBinaryProtocol(self.transport)
 
-        self.transport = TSocket.TSocket('localhost', 9090)
-        self.transport = TTransport.TBufferedTransport(self.transport)
+    def __enter__(self):
+        self.open()
+        return self
 
-        self.protocol = TBinaryProtocol.TBinaryProtocol(self.transport)
+    def __exit__(self, *args):
+        self.close()
 
+    def start_server(self):
+        self.interop_proc = subprocess.Popen(
+            ["java", "-Dlog4j.configurationFile=../lib/log4j2.xml", "-jar", "../lib/interop-server.jar"]
+        )
         try:
-            self.transport.open()
-        except TTransportException:
-            raise PlcException("Unable to connect to the Interop Server, is the Server really running???")
+            print("Started server under pid " + str(self.interop_proc.pid))
+        except:
+            print("Encountered an Exception while starting Interop Server")
+            raise PlcException("Unable to start the Interop Server!")
+        time.sleep(2)
+        poll = self.interop_proc.poll()
+        if poll is None:
+            print("Sucesfully started the Interop Server...")
+        else:
+            warnings.warn("Interop Server died after starting up...")
+            raise PlcException(
+                "Unable to start the Interop Server. Is another Server still running under the same port?")
 
     def _get_client(self):
         return Client(self.protocol)
@@ -70,6 +74,28 @@ class PlcDriverManager:
     def get_connection(self, url):
         return PlcConnection(self._get_client(), url)
 
+    @contextmanager
+    def connection(self, url):
+        """
+        Context manager to handle connection.
+        """
+        conn = None
+        try:
+            conn = self.get_connection(url)
+            yield conn
+        except PlcException as e:
+            raise Exception(str(e.url))
+        finally:
+            if conn is not None:
+                conn.close()
+
+    def open(self):
+        try:
+            self.transport.open()
+        except TTransportException:
+            self.close()  # Handle failure on enter
+            raise PlcException("Unable to connect to the Interop Server, is the Server really running?")
+
     def close(self):
         print("Closing the Interop Server")
         try: