You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by sj...@apache.org on 2021/05/20 16:15:55 UTC

[flink-statefun] branch master updated: [FLINK-22242][python] Improve missing attribute error on GeneratedAddressedScopedStorage

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

sjwiesman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink-statefun.git


The following commit(s) were added to refs/heads/master by this push:
     new a239958  [FLINK-22242][python] Improve missing attribute error on GeneratedAddressedScopedStorage
a239958 is described below

commit a23995878ca12c4f25f08751fad91f1275e1df80
Author: Seth Wiesman <sj...@gmail.com>
AuthorDate: Mon Apr 12 11:32:01 2021 -0500

    [FLINK-22242][python] Improve missing attribute error on GeneratedAddressedScopedStorage
    
    This closes #223
---
 statefun-sdk-python/statefun/request_reply_v3.py |  2 +-
 statefun-sdk-python/statefun/storage.py          | 16 +++++++++++++---
 statefun-sdk-python/tests/storage_test.py        | 10 +++++-----
 3 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/statefun-sdk-python/statefun/request_reply_v3.py b/statefun-sdk-python/statefun/request_reply_v3.py
index 3eb258f..fa05253 100644
--- a/statefun-sdk-python/statefun/request_reply_v3.py
+++ b/statefun-sdk-python/statefun/request_reply_v3.py
@@ -209,7 +209,7 @@ class RequestReplyHandler(object):
         if not target_fn:
             raise ValueError(f"Unable to find a function of type {sdk_address.typename}")
         # resolve state
-        res = resolve(target_fn.storage_spec, pb_to_function.invocation.state)
+        res = resolve(target_fn.storage_spec, sdk_address.typename, pb_to_function.invocation.state)
         if res.missing_specs:
             pb_from_function = collect_failure(res.missing_specs)
             return pb_from_function.SerializeToString()
diff --git a/statefun-sdk-python/statefun/storage.py b/statefun-sdk-python/statefun/storage.py
index 0eafe94..21a49fe 100644
--- a/statefun-sdk-python/statefun/storage.py
+++ b/statefun-sdk-python/statefun/storage.py
@@ -68,8 +68,13 @@ class Cell(object):
 # self.cells: typing.Dict[str, Cell] = {name: Cell(name, tpe, vals[name]) for name, tpe in types.items()}
 
 
-def storage_constructor(self, cells: typing.Dict[str, Cell]):
+def storage_constructor(self, cells: typing.Dict[str, Cell], typename: str):
     self._cells = cells
+    self._typename = typename
+
+
+def storage_missing_attribute(self, attr):
+    raise AttributeError("'{}' is not a registered ValueSpec for the function '{}'".format(attr, self._typename))
 
 
 def property_named(name):
@@ -109,7 +114,10 @@ def make_address_storage_spec(specs: typing.List[ValueSpec]) -> StorageSpec:
     :param specs: a list of specs as supplied by the user.
     :return: a StorageSpec.
     """
-    props = {"__init__": storage_constructor, "__slots__": ["_cells"]}
+    props = {
+        "__init__": storage_constructor,
+        "__getattr__": storage_missing_attribute,
+        "__slots__": ["_cells", "_typename"]}
     for spec in specs:
         if spec.name in props:
             raise ValueError("duplicate registered value name: " + spec.name)
@@ -121,11 +129,13 @@ def make_address_storage_spec(specs: typing.List[ValueSpec]) -> StorageSpec:
 
 
 def resolve(storage: StorageSpec,
+            typename: str,
             values: typing.List[ToFunction.PersistedValue]) -> Resolution:
     """
     Resolve the registered specs and the actually received values.
 
     :param storage: a storage factory
+    :param typename: the typename of the function under invocation
     :param values: the actually received values
     :return: a Resolution result, that might have either a list of missing specs
     (specs that were defined by the user but didn't arrived from StateFun) or a
@@ -148,5 +158,5 @@ def resolve(storage: StorageSpec,
     else:
         cells: typing.Dict[str, Cell] = {spec.name: Cell(tpe=spec.type, typed_value=received[spec.name]) for spec in
                                          storage.specs}
-        s = storage.make_instance(cells)
+        s = storage.make_instance(cells, typename)
         return Resolution(missing_specs=None, storage=s)
diff --git a/statefun-sdk-python/tests/storage_test.py b/statefun-sdk-python/tests/storage_test.py
index 2e99cd2..dd4a9ed 100644
--- a/statefun-sdk-python/tests/storage_test.py
+++ b/statefun-sdk-python/tests/storage_test.py
@@ -39,7 +39,7 @@ class StorageTestCase(unittest.TestCase):
         values = [PbPersistedValueLike("a", 1, IntType), PbPersistedValueLike("b", "hello", StringType)]
 
         # resolve spec and values
-        resolution = resolve(storage_spec, values)
+        resolution = resolve(storage_spec, "example/func", values)
         store = resolution.storage
 
         self.assertEqual(store.a, 1)
@@ -53,7 +53,7 @@ class StorageTestCase(unittest.TestCase):
         values = []
 
         # resolve spec and values
-        resolution = resolve(storage_spec, values)
+        resolution = resolve(storage_spec, "example/func", values)
         self.assertListEqual(resolution.missing_specs, specs)
 
     def test_partial_failed_resolution(self):
@@ -64,7 +64,7 @@ class StorageTestCase(unittest.TestCase):
         values = [PbPersistedValueLike("a", 1, IntType)]
 
         # resolve spec and values
-        resolution = resolve(storage_spec, values)
+        resolution = resolve(storage_spec, "example/func", values)
         self.assertListEqual(resolution.missing_specs, specs[1:])
 
     def test_ignore_unknown(self):
@@ -75,7 +75,7 @@ class StorageTestCase(unittest.TestCase):
         values = [PbPersistedValueLike("a", 1, IntType), PbPersistedValueLike("b", "hello", StringType)]
 
         # resolve spec and values
-        resolution = resolve(storage_spec, values)
+        resolution = resolve(storage_spec, "example/func", values)
         store = resolution.storage
 
         self.assertEqual(store.a, 1)
@@ -157,5 +157,5 @@ def store_from(*args):
         else:
             vals.append(arg)
     storage_spec = make_address_storage_spec(specs)
-    resolution = resolve(storage_spec, vals)
+    resolution = resolve(storage_spec, "example/func", vals)
     return resolution.storage