Exemple #1
0
    def test_protobuf_copy(self):
        """
        Copy to and back from a Protobuf type and ensure the original object is the same as the copy.
        :return:
        """
        logging.info("Test copy to/from a protobuf type")
        message1 = Message1(field='Message-687',
                            state=State.S2,
                            tasks=[
                                Task(task_name="Task-1", task_id=1),
                                Task(task_name="Task-2", task_id=2)
                            ],
                            strings=["A", "2", "c", "4", "D"],
                            _double=3.142,
                            _float=6.284,
                            _int32=496,
                            _int64=8128,
                            _bool=True,
                            _bytes=b'A Byte String')

        pb_message1 = PBMessage1()
        actual = DCCopy.deep_corresponding_copy(message1, pb_message1)
        try:
            actual.SerializeToString()
        except Exception:
            self.fail("Profbuf object invalid after copy as cannot serialize")
        message2 = Message1()
        final = DCCopy.deep_corresponding_copy(actual, message2)
        self.assertEqual(final, message1)

        return
Exemple #2
0
    def test_enum(self):
        logging.info("Test enum specifics")
        # Pass case
        src = Z(AnEnumInt.S1, AnEnumStr.S2)
        tgt = Z(AnEnumInt.S0, AnEnumStr.S0)
        tgt = DCCopy.deep_corresponding_copy(src, tgt)
        self.assertEqual(tgt, src)

        # Pass case reverse as it's valid to copy a str Enum over an Int Enum
        src = Z(AnEnumInt.S1, AnEnumStr.S2)
        tgt = Z(AnEnumStr.S0, AnEnumInt.S0)  # Reverse int/str type Enum
        tgt = DCCopy.deep_corresponding_copy(src, tgt)
        self.assertEqual(tgt, src)
        return
Exemple #3
0
    def test_enum_to_value_type(self):
        # Pass case, target types align with value type
        src = Z(AnEnumInt.S2, AnEnumStr.S1)
        tgt = Z(int(3142), "3142")
        tgt = DCCopy.deep_corresponding_copy(src, tgt)
        self.assertEqual(tgt._a, src._a.value)
        self.assertEqual(tgt._b, src._b.value)

        # Fail case target type not same as value type
        src = Z(AnEnumInt.S2, AnEnumStr.S1)
        tgt = Z("3142", int(3142))
        with self.assertRaises(TypeError):
            _ = DCCopy.deep_corresponding_copy(src=src, tgt=tgt)

        return
Exemple #4
0
 def test_simple(self):
     logging.info("Test simple base types and collections")
     scenarios = [[int(678), int(0), int(678)], [[1, 2], [6, 7], [1, 2]],
                  [[1, 2], [6, 7, 8], [1, 2, 8]],
                  [[1, 2, 3, 4], [6, 7, 8], [1, 2, 3, 4]],
                  [dict(), dict(), dict()], [{
                      1: 2
                  }, {
                      1: 3
                  }, {
                      1: 2
                  }], [{
                      1: 2,
                      2: 3
                  }, {
                      1: 2,
                      2: 5,
                      3: 4
                  }, {
                      1: 2,
                      2: 3,
                      3: 4
                  }],
                  [{
                      1: [Z({
                          1: 2,
                          2: 3
                      }, [3, 4, 5])],
                      3: "4",
                      4: True
                  }, {
                      1: [Z({
                          1: 3,
                          3: 4
                      }, [1, 4, 5, 4])],
                      3: "5",
                      4: False,
                      7: AnEnumInt.S1
                  }, {
                      1: [Z({
                          1: 2,
                          2: 3,
                          3: 4
                      }, [3, 4, 5, 4])],
                      3: "4",
                      4: True,
                      7: AnEnumInt.S1
                  }],
                  [
                      Z(Z(Z(Z(Z(1, 2), 3), 4), 5), 6),
                      Z(Z(Z(Z(Z(9, 8), 7), 6), 5), 4),
                      Z(Z(Z(Z(Z(1, 2), 3), 4), 5), 6)
                  ], [[[1, 2], 3], [[4, 5], 6], [[1, 2], 3]],
                  [[[[[[float(0)]]]]], [[[[[float(1)]]]]],
                   [[[[[float(0)]]]]]]]
     for scenario in scenarios:
         src, tgt, expected = scenario
         self.assertEqual(expected,
                          DCCopy.deep_corresponding_copy(src=src, tgt=tgt))
     return
Exemple #5
0
 def test_enum_with_members(self):
     src = Z(AnEnumWithMembers.S0, AnEnumInt.S0)
     tgt = Z(AnEnumWithMembers.S1, AnEnumInt.S2)
     tgt = DCCopy.deep_corresponding_copy(src, tgt)
     self.assertEqual(tgt, src)
     self.assertEqual((1 * 2), src._a.func)
     return
Exemple #6
0
 def test_simple_obj(self):
     logging.info("Test simple, un-nested object")
     src = Z(A(1, 2, 3, 4), B(5, 6, 7, 8))
     tgt = Z(A(10, 12, 13, 14), B(15, 16, 17, 18))
     tgt = DCCopy.deep_corresponding_copy(src=src, tgt=tgt)
     self.assertEqual(src, tgt)
     return
Exemple #7
0
 def test_prune_fails(self):
     logging.info("Test prune failure cases")
     z1a = 1
     z1b = 2
     z2a = 3
     z2b = 4
     scenarios = [1, [1], bool, [bool], 3.142, [3.142], ['_b', 123]]
     for p in scenarios:
         z1 = Z(z1a, z1b)
         z2 = Z(z2a, z2b)
         with self.assertRaises(TypeError):
             _ = DCCopy.deep_corresponding_copy(src=z1, tgt=z2, prune=p)
     return
Exemple #8
0
 def serialize(self,
               src: object) -> bytes:
     """
     Take the given object and serialise it using it's registered protobuf partner object
     :param src: The object to be serialised. The object type must have been registered with
     its protobuf partner.
     :return:
     """
     obj_type = type(src).__name__
     if obj_type not in self._transform_map:
         raise ValueError("Object of type {} has no registered serializer".format(obj_type))
     tgt = DCCopy.deep_corresponding_copy(src=src, tgt=self._transform_map[obj_type][ProtoCopy._PROTOBUF_TYPE]())
     return tgt.SerializeToString()
Exemple #9
0
 def test_fails(self):
     logging.info("Test failure cases for type mismatch")
     scenarios = [[int(0), float(0)], [AnEnumInt.S1,
                                       bool(True)], [AnEnumStr.S2,
                                                     int(0)],
                  [list(), dict()], [[int(0), float(0)], [int(0),
                                                          int(0)]],
                  [list(), Z(1, 2)], [Z(1.0, 2), Z(3, 4)],
                  [Z([1, 2, 3], "Hi"),
                   Z([1, 2.0], "Lo")]]
     for scenario in scenarios:
         src, tgt = scenario
         with self.assertRaises(TypeError):
             _ = DCCopy.deep_corresponding_copy(src=src, tgt=tgt)
     return
Exemple #10
0
 def test_prune(self):
     logging.info("Test prune sunshine cases")
     z1a = 1
     z1b = 2
     z2a = 3
     z2b = 4
     scenarios = [[None, z1a, z1b], [[None], z1a, z1b], ['', z1a, z1b],
                  ['_a', z2a, z1b], [['a', 'a_', 'x', 'b', 'b_'], z1a, z1b],
                  [['_a'], z2a, z1b], [['_a', '_a'], z2a, z1b]]
     for p, expected_a, expected_b in scenarios:
         z1 = Z(z1a, z1b)
         z2 = Z(z2a, z2b)
         actual = DCCopy.deep_corresponding_copy(src=z1, tgt=z2, prune=p)
         self.assertEqual(actual._a, expected_a)
         self.assertEqual(actual._b, expected_b)
     return
Exemple #11
0
 def test_fields_rev(self):
     logging.info(
         "Test simple object to object with only partial member field overlap B -> A"
     )
     # B -> A
     src = B(4, 5.0, "6", AnEnumInt.S2)
     tgt = A(1, 2.0, "3", AnEnumInt.S0)
     tgt_unmod = A(1, 2.0, "3", AnEnumInt.S0)
     actual = DCCopy.deep_corresponding_copy(src, tgt)
     self.assertEqual(src._a, actual._a)  # Corresponding & updated
     self.assertEqual(
         getattr(tgt_unmod, "_{}__b".format(type(tgt_unmod).__name__)),
         getattr(actual, "_{}__b".format(
             type(actual).__name__)))  # .__b hidden & not updated
     self.assertEqual(tgt_unmod._ca,
                      actual._ca)  # Not corresponding & not updated
     self.assertEqual(src.d, actual.d)  # Corresponding & updated
     self.assertEqual(tgt._ae,
                      actual._ae)  # Not Corresponding & const on __init__
     return
Exemple #12
0
 def deserialize(self,
                 serialized_src: bytes,
                 target_type: Type) -> object:
     """
     Take the given ByteString and deserialize it as the given type
     :param serialized_src: The required object as a ByteString
     :param target_type: The type of object to deserialize as. This must have been registered() with it't
     protobuf partner.
     :return:
     """
     if serialized_src is None or len(serialized_src) == 0 or not isinstance(serialized_src, bytes):
         raise ValueError("serialized_src must be a non zero length ByteString")
     obj_type = target_type.__name__
     if obj_type not in self._transform_map:
         raise ValueError("Object of type {} has no registered deserializer".format(target_type))
     pbt = self._transform_map[obj_type][ProtoCopy._PROTOBUF_TYPE]()
     tgt = self._transform_map[obj_type][ProtoCopy._OBJECT_TYPE]()
     pbt.ParseFromString(serialized_src)
     tgt = DCCopy.deep_corresponding_copy(src=pbt, tgt=tgt)
     return tgt
Exemple #13
0
    def test_complex_nested(self):
        logging.info(
            "Test complex nested object, with base types, collections, Enum etc"
        )
        actual = DCCopy.deep_corresponding_copy(X(), Y())
        expected = X()
        target_unmodified = Y()

        # Top Level - with over lap
        self.assertEqual(expected._n, actual._n)
        self.assertEqual(expected._an_enum, actual._an_enum)

        # Top Level - no over lap or hidden
        self.assertEqual(target_unmodified._y,
                         actual._y)  # ._y not shared, should not be overridden
        self.assertEqual(
            getattr(target_unmodified,
                    "_{}__hidden".format(type(target_unmodified).__name__)),
            getattr(actual, "_{}__hidden".format(
                type(actual).__name__)))  # ._hidden should be same

        # Contained object
        self.assertEqual(expected._z._a, actual._z._a)
        self.assertEqual(expected._z._b, actual._z._b)

        # Inherited
        self.assertEqual(expected._base_s, actual._base_s)
        self.assertEqual(expected._base_b, actual._base_b)
        self.assertEqual(expected._base_n, actual._base_n)
        self.assertEqual(expected._base_i, actual._base_i)
        self.assertEqual(expected._base_f, actual._base_f)

        # Simple Lists
        self.assertEqual(target_unmodified._l_1, actual._l_1)
        self.assertEqual(expected._l_2, actual._l_2)
        self.assertEqual(expected._l_3, actual._l_3)
        self.assertEqual([.7, .9, .11, .12], actual._l_4)
        self.assertEqual(expected._l_5, actual._l_5)
        self.assertEqual([[1, 2, 3], .4, .13], actual._l_6)

        # Heterogeneous lists with objects
        self.assertEqual(expected._l_7, actual._l_7)
        self.assertEqual(
            [False, [Z(11, 13), Z(22, 23), Z(24, 25)]], actual._l_8)

        # Simple dictionaries
        self.assertEqual(expected._d_1, actual._d_1)
        self.assertEqual(expected._d_2, actual._d_2)

        # Complex dictionaries
        self.assertEqual(expected._d_3, actual._d_3)
        self.assertEqual(target_unmodified._d_4, actual._d_4)
        self.assertEqual(
            {
                '1': 1,
                '2': True,
                '3': 1.2,
                '4': ['a', 1, True, 'xray'],
                '5': Z(5, 6),
                '6': 'added'
            }, actual._d_5)
        return