Skip to content

Commit

Permalink
[#469] Implement cppbind helper for loading of C++ optimized code
Browse files Browse the repository at this point in the history
  • Loading branch information
Mi-La committed Jan 25, 2023
1 parent d3b4ec8 commit 61a86f9
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
41 changes: 41 additions & 0 deletions compiler/extensions/python/runtime/src/zserio/cppbind.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""
The module provides helper for importing of optimized C++ classes.
"""

import importlib
import os
import typing

from zserio.exception import PythonRuntimeException

ZSERIO_PYTHON_IMPLEMENTATION_ENV = "ZSERIO_PYTHON_IMPLEMENTATION"
ZSERIO_CPP_MODULE = "zserio_cpp"

def import_cpp_class(cppname: str) -> typing.Optional[typing.Type[typing.Any]]:
"""
Tries to import optimized C++ implementation of the given python class if 'ZSERIO_PYTHON_IMPLEMENTATION'
environment variable is either unset or set to 'cpp'.
Depending on the content of the 'ZSERIO_PYTHON_IMPLEMENTATION' environment variable,
it either fails when no C++ implementation is available ('cpp') or ignores missing implementation
and just return the original python class (None) or even does not try to load the C++ implementation if
the variable is set to anyhing else (e.g. 'python').
:param pyclass: Pure python class implemenation for which the C++ optimized version should be loaded.
:param cppname: Name of optimized C++ class in case that it differs from the pyclass name.
:returns: Requested implemenation of the given pyclass.
:raises PythonRuntimeException: When the requested implementation is not available.
"""

impl = os.getenv(ZSERIO_PYTHON_IMPLEMENTATION_ENV)
if not impl in [None, "python", "cpp", "c++"]:
raise PythonRuntimeException(f"Zserio Python runtime implementation '{impl}' is not available!")

if impl != "python":
try:
return getattr(importlib.import_module(ZSERIO_CPP_MODULE), cppname)
except (ImportError, AttributeError) as err:
if impl in ["cpp", "c++"]:
message = f"Zserio C++ implementation of '{cppname}' is not available!"
raise PythonRuntimeException(message) from err
return None
4 changes: 2 additions & 2 deletions compiler/extensions/python/runtime/tests/test_bitposition.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import unittest

from zserio.bitposition import (alignto, bits_to_bytes, bytes_to_bits, bitsize_to_bytesize,
PythonRuntimeException)
from zserio.bitposition import (alignto, bits_to_bytes, bytes_to_bits, bitsize_to_bytesize)
from zserio.exception import PythonRuntimeException

class BitPositionTest(unittest.TestCase):

Expand Down
30 changes: 30 additions & 0 deletions compiler/extensions/python/runtime/tests/test_cppbind.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import unittest
import os

from zserio.cppbind import import_cpp_class
from zserio.exception import PythonRuntimeException

class MissingCppClass:
pass

class CppBindTest(unittest.TestCase):

def test_invalid_env(self):
os.environ["ZSERIO_PYTHON_IMPLEMENTATION"] = "invalid"
with self.assertRaises(PythonRuntimeException):
import_cpp_class(MissingCppClass)

def test_missing_cpp_default(self):
os.environ.pop("ZSERIO_PYTHON_IMPLEMENTATION")
imported = import_cpp_class(MissingCppClass)
self.assertEqual(MissingCppClass, imported)

def test_missing_cpp_python(self):
os.environ["ZSERIO_PYTHON_IMPLEMENTATION"] = "python"
imported = import_cpp_class(MissingCppClass)
self.assertEqual(MissingCppClass, imported)

def test_missing_cpp_cpp(self):
os.environ["ZSERIO_PYTHON_IMPLEMENTATION"] = "cpp"
with self.assertRaises(PythonRuntimeException):
import_cpp_class(MissingCppClass)

0 comments on commit 61a86f9

Please sign in to comment.