vortexpy 4.0.23__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. vortex/DataWrapTuple.py +27 -0
  2. vortex/DeferUtil.py +224 -0
  3. vortex/Jsonable.py +304 -0
  4. vortex/Payload.py +115 -0
  5. vortex/PayloadEndpoint.py +216 -0
  6. vortex/PayloadEndpointTest.py +164 -0
  7. vortex/PayloadEnvelope.py +166 -0
  8. vortex/PayloadFilterKeys.py +15 -0
  9. vortex/PayloadIO.py +152 -0
  10. vortex/PayloadPriority.py +11 -0
  11. vortex/PayloadResponse.py +173 -0
  12. vortex/PayloadResponseTest.py +39 -0
  13. vortex/PayloadTest.py +136 -0
  14. vortex/PerformTestActionTuple.py +30 -0
  15. vortex/SerialiseUtil.py +273 -0
  16. vortex/TestTuple.py +61 -0
  17. vortex/Tuple.py +968 -0
  18. vortex/TupleAction.py +72 -0
  19. vortex/TupleActionVortex.py +5 -0
  20. vortex/TupleDataForTest.py +25 -0
  21. vortex/TuplePerfTest.py +71 -0
  22. vortex/TuplePolymorphicTupleTypeFieldArgTest.py +74 -0
  23. vortex/TupleRestfulTest.py +140 -0
  24. vortex/TupleSelector.py +105 -0
  25. vortex/TupleTest.py +127 -0
  26. vortex/VortexABC.py +55 -0
  27. vortex/VortexClientHttp.py +308 -0
  28. vortex/VortexClientHttpTest.py +71 -0
  29. vortex/VortexClientTcp.py +355 -0
  30. vortex/VortexClientWebsocketFactory.py +383 -0
  31. vortex/VortexConnectionABC.py +88 -0
  32. vortex/VortexFactory.py +932 -0
  33. vortex/VortexPayloadProtocol.py +180 -0
  34. vortex/VortexServer.py +367 -0
  35. vortex/VortexServerConnection.py +127 -0
  36. vortex/VortexServerHttpResource.py +193 -0
  37. vortex/VortexServerTcp.py +104 -0
  38. vortex/VortexServerWebsocket.py +287 -0
  39. vortex/VortexTcpMemoryLeakPayloadTest.py +611 -0
  40. vortex/VortexTcpMemoryLeakRawTest.py +87 -0
  41. vortex/VortexTest.py +22 -0
  42. vortex/VortexUtil.py +314 -0
  43. vortex/VortexWritePushProducer.py +321 -0
  44. vortex/__init__.py +10 -0
  45. vortex/data_loader/TupleDataLiveLockManager.py +383 -0
  46. vortex/data_loader/TupleDataLoader.py +326 -0
  47. vortex/data_loader/TupleDataLoaderDelegate.py +90 -0
  48. vortex/data_loader/TupleDataLoaderTupleABC.py +10 -0
  49. vortex/data_loader/TupleDataLoaderTuples.py +53 -0
  50. vortex/data_loader/__init__.py +0 -0
  51. vortex/event_bus/TupleChangeEventABC.py +15 -0
  52. vortex/event_bus/TupleChangeEventBus.py +192 -0
  53. vortex/event_bus/TupleChangeEventBusObserverABC.py +11 -0
  54. vortex/event_bus/__init__.py +0 -0
  55. vortex/handler/TupleActionProcessor.py +270 -0
  56. vortex/handler/TupleActionProcessorProxy.py +218 -0
  57. vortex/handler/TupleActionProcessorTestHandler.py +27 -0
  58. vortex/handler/TupleDataActionClient.py +67 -0
  59. vortex/handler/TupleDataObservableCache.py +201 -0
  60. vortex/handler/TupleDataObservableHandler.py +371 -0
  61. vortex/handler/TupleDataObservableProxyHandler.py +340 -0
  62. vortex/handler/TupleDataObservableTestHandler.py +60 -0
  63. vortex/handler/TupleDataObserverClient.py +158 -0
  64. vortex/handler/VortexJSTupleLoaderTestHandler.py +42 -0
  65. vortex/handler/__init__.py +0 -0
  66. vortex/restful/GzippedDataHttpClient.py +170 -0
  67. vortex/restful/GzippedDataHttpClientTest.py +103 -0
  68. vortex/restful/GzippedPayloadHttpClient.py +181 -0
  69. vortex/restful/RestfulHttpClient.py +107 -0
  70. vortex/restful/RestfulHttpClientTest.py +60 -0
  71. vortex/restful/RestfulResource.py +153 -0
  72. vortex/restful/RestfulResourceTest.py +100 -0
  73. vortex/restful/__init__.py +0 -0
  74. vortex/rpc/RPC.py +446 -0
  75. vortex/rpc/RPCTest.py +12 -0
  76. vortex/rpc/__init__.py +0 -0
  77. vortex/sqla_orm/OrmCrudHandler.py +431 -0
  78. vortex/sqla_orm/TupleProviderForDb.py +42 -0
  79. vortex/sqla_orm/VortexTupleJson.py +24 -0
  80. vortex/sqla_orm/__init__.py +0 -0
  81. vortex/storage/TupleStorageSqlite.py +359 -0
  82. vortex/storage/__init__.py +0 -0
  83. vortexpy-4.0.23.dist-info/LICENSE +21 -0
  84. vortexpy-4.0.23.dist-info/METADATA +43 -0
  85. vortexpy-4.0.23.dist-info/RECORD +87 -0
  86. vortexpy-4.0.23.dist-info/WHEEL +5 -0
  87. vortexpy-4.0.23.dist-info/top_level.txt +1 -0
vortex/TupleAction.py ADDED
@@ -0,0 +1,72 @@
1
+ """
2
+ * Created by Synerty Pty Ltd
3
+ *
4
+ * This software is open source, the MIT license applies.
5
+ *
6
+ * Website : http://www.synerty.com
7
+ * Support : support@synerty.com
8
+ """
9
+ import uuid
10
+ from datetime import datetime
11
+ from typing import Dict
12
+ from typing import List
13
+
14
+ import pytz
15
+
16
+ from vortex.Tuple import Tuple
17
+ from vortex.Tuple import TupleField
18
+ from vortex.Tuple import addTupleType
19
+ from vortex.TupleSelector import TupleSelector
20
+
21
+
22
+ class TupleActionABC(Tuple):
23
+ uuid: str = TupleField(
24
+ comment="Uniquely generated id for this action", typingType=str
25
+ )
26
+ dateTime: datetime = TupleField(
27
+ comment="The datetime this action was created", typingType=datetime
28
+ )
29
+
30
+ def __init__(self, **kwargs):
31
+ if not self.__tupleType__:
32
+ raise NotImplementedError(
33
+ "TupleActionABC can not be instantiated,"
34
+ " please inherit it and implement a tuple"
35
+ )
36
+
37
+ Tuple.__init__(self, **kwargs)
38
+
39
+ if not "uuid" in kwargs:
40
+ self.uuid = str(uuid.uuid1()) # Based on the host, and the time
41
+
42
+ if not "dateTime" in kwargs:
43
+ self.dateTime = datetime.now(pytz.utc)
44
+
45
+
46
+ @addTupleType
47
+ class TupleGenericAction(TupleActionABC):
48
+ """Tuple Generic Action
49
+
50
+ This is a generic action, to be used when the implementor doesn't want to implement
51
+ concrete classes for each action type.
52
+
53
+ """
54
+
55
+ __tupleType__ = "vortex.TupleGenericAction"
56
+
57
+ key = TupleField(comment="An optional key for this action", typingType=str)
58
+
59
+ data = TupleField(comment="Optional data for the update", typingType=str)
60
+
61
+
62
+ @addTupleType
63
+ class TupleUpdateAction(TupleActionABC):
64
+ __tupleType__ = "vortex.TupleUpdateAction"
65
+
66
+ tupleSelector = TupleField(
67
+ comment="The tuple selector for this action", typingType=TupleSelector
68
+ )
69
+ tupleChanges = TupleField(
70
+ comment="An array of {old:v,new:v} dicts for the changes",
71
+ typingType=List[Dict],
72
+ )
@@ -0,0 +1,5 @@
1
+ class TupleActionVortex:
2
+ def __init__(self, vortexName, vortexUuid, httpSession):
3
+ self.name = vortexName
4
+ self.uuid = vortexUuid
5
+ self.httpSession = httpSession
@@ -0,0 +1,25 @@
1
+ """
2
+ * Created by Synerty Pty Ltd
3
+ *
4
+ * This software is open source, the MIT license applies.
5
+ *
6
+ * Website : http://www.synerty.com
7
+ * Support : support@synerty.com
8
+ """
9
+ from vortex.TestTuple import TestTuple
10
+
11
+
12
+ def makeTestTupleData(count=5):
13
+ tuples = []
14
+ for num in range(count):
15
+ uniStr = "#%s double hyphen :-( — “fancy quotes”" % num
16
+ tuples.append(
17
+ TestTuple(
18
+ aInt=num,
19
+ aBoolTrue=bool(num % 2),
20
+ aString="This is tuple #%s" % num,
21
+ aStrWithUnicode=uniStr,
22
+ )
23
+ )
24
+
25
+ return tuples
@@ -0,0 +1,71 @@
1
+ import gc
2
+ import os
3
+ from datetime import datetime
4
+
5
+ import psutil
6
+ import pytz
7
+
8
+ process = psutil.Process(os.getpid())
9
+
10
+ ITER_COUNT = 1000 * 1000 * 5
11
+
12
+ RESULT = None
13
+
14
+
15
+ def makeL(i):
16
+ # Use this line to negate the effect of the strings on the test
17
+ # return "Python is smart and will only create one string with this line"
18
+
19
+ # Use this if you want to see the difference with 5 million unique strings
20
+ return "This is a sample string %s" % i
21
+
22
+
23
+ def timeit(method):
24
+ def timed(*args, **kw):
25
+ global RESULT
26
+ RESULT = None
27
+ gc.collect()
28
+
29
+ s = datetime.now(pytz.utc)
30
+ startMem = process.memory_info().rss
31
+ RESULT = method(*args, **kw)
32
+ e = datetime.now(pytz.utc)
33
+ endMem = process.memory_info().rss
34
+
35
+ sizeMb = (endMem - startMem) / 1024 / 1024
36
+ sizeMbStr = "{0:,}".format(round(sizeMb, 2))
37
+
38
+ print(
39
+ "Time Taken = %s, \t%s, \tSize = %s"
40
+ % (e - s, method.__name__, sizeMbStr)
41
+ )
42
+
43
+ return timed
44
+
45
+
46
+ from vortex.Tuple import Tuple, addTupleType, TupleHash
47
+ from vortex.Payload import Payload
48
+
49
+
50
+ @addTupleType
51
+ class X(Tuple):
52
+ __tupleType__ = "X"
53
+ __slots__ = ["i", "l"]
54
+
55
+ def __init__(self, i=None, l=None):
56
+ self.i, self.l = i, l
57
+
58
+
59
+ @timeit
60
+ def provile_dict_of_nt():
61
+ return [X(i=i, l=makeL(i)) for i in range(ITER_COUNT)]
62
+
63
+
64
+ if __name__ == "__main__":
65
+ provile_dict_of_nt()
66
+
67
+ tupleIn = X("val1", "val2")
68
+ encodedPayload = Payload(tuples=[tupleIn]).toEncodedPayload()
69
+ payload = Payload().fromEncodedPayload(encodedPayload)
70
+
71
+ assert TupleHash(tupleIn) == TupleHash(payload.tuples[0])
@@ -0,0 +1,74 @@
1
+ import logging
2
+ import unittest
3
+
4
+ from vortex.Tuple import (
5
+ Tuple,
6
+ addTupleType,
7
+ TupleField,
8
+ PolymorphicTupleTypeFieldArg,
9
+ TupleHash,
10
+ )
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ @addTupleType
16
+ class Parent(Tuple):
17
+ __tupleType__ = "com.synerty.Tuples.Parent"
18
+ __tupleArgs__ = (PolymorphicTupleTypeFieldArg("concreteType"),)
19
+
20
+ aStr: str = TupleField()
21
+ concreteType: str = TupleField()
22
+
23
+
24
+ @addTupleType
25
+ class Child(Parent):
26
+ __tupleType__ = "com.synerty.Tuples.Child"
27
+
28
+ aInt: int = TupleField()
29
+
30
+
31
+ @addTupleType
32
+ class Another(Tuple):
33
+ __tupleType__ = "com.synerty.Tuples.Another"
34
+
35
+ aInt: int = TupleField()
36
+ concreteType: str = TupleField()
37
+
38
+
39
+ class PolymorphicTupleTypeFieldArgTest(unittest.TestCase):
40
+ def testParentTupleToFromJSON(self):
41
+ parent1 = Parent(aStr="Test", concreteType=Parent.tupleType())
42
+ parent2 = Parent(aStr="Test", concreteType=Parent.tupleType())
43
+ parent3 = Parent(aStr="Test 1", concreteType=Parent.tupleType())
44
+
45
+ self.assertEqual(TupleHash(parent1), TupleHash(parent2))
46
+ self.assertNotEqual(TupleHash(parent1), TupleHash(parent3))
47
+
48
+ def testChildFieldsInToJsonDict(self):
49
+ data = dict(aStr="Test", aInt=1, concreteType=Child.tupleType())
50
+ child = Child(**data)
51
+
52
+ self.assertEqual(data, child.tupleToRestfulJsonDict())
53
+
54
+ def testChildTupleToFromJSON(self):
55
+ # Construct Child through Child
56
+ child1 = Child(aStr="Test", aInt=1, concreteType=Child.tupleType())
57
+
58
+ # Construct Child through Parent
59
+ child2 = Tuple.restfulJsonDictToTupleWithValidation(
60
+ child1.tupleToRestfulJsonDict(), Parent
61
+ )
62
+
63
+ self.assertEqual(TupleHash(child1), TupleHash(child2))
64
+
65
+ # Parent should not match Child
66
+ parent1 = Parent(aStr="Test", concreteType=Parent.tupleType())
67
+ self.assertNotEqual(TupleHash(child1), TupleHash(parent1))
68
+
69
+ # Parent should only be able to init its children
70
+ another1 = Another(aInt=1, concreteType=Another.tupleType())
71
+ with self.assertRaises(TypeError):
72
+ Tuple.restfulJsonDictToTupleWithValidation(
73
+ another1.tupleToRestfulJsonDict(), Parent
74
+ )
@@ -0,0 +1,140 @@
1
+ """
2
+ * Created by Synerty Pty Ltd
3
+ *
4
+ * This software is open source, the MIT license applies.
5
+ *
6
+ * Website : http://www.synerty.com
7
+ * Support : support@synerty.com
8
+ """
9
+
10
+ import json
11
+ from typing import Dict, Annotated
12
+ from typing import List
13
+ from typing import Union
14
+
15
+ from ddt import data, ddt
16
+ from twisted.trial import unittest
17
+
18
+ from vortex.Tuple import Tuple
19
+ from vortex.Tuple import TupleField
20
+ from vortex.Tuple import TupleHash, IntTupleFieldValidator
21
+ from vortex.Tuple import addTupleType
22
+
23
+
24
+ @addTupleType
25
+ class RestfulTestTuple(Tuple):
26
+ """
27
+ classdocs
28
+ """
29
+
30
+ __tupleType__ = "synerty.vortex.RestfulTestTuple"
31
+ aInt: int = TupleField()
32
+ aIntWithValidator: Annotated[
33
+ int, IntTupleFieldValidator(1, 100)
34
+ ] = TupleField()
35
+ aFloat: float = TupleField()
36
+ aString: str = TupleField()
37
+ aBoolTrue: bool = TupleField()
38
+ aBoolFalse: bool = TupleField()
39
+ aList: List[Union[str, int, bool, float]] = TupleField()
40
+ aDict: Dict[str, Union[str, float]] = TupleField()
41
+ aSubTuple: "RestfulSubTestTuple" = TupleField()
42
+ aListOfSubTuples: List["RestfulSubTestTuple"] = TupleField()
43
+ aDictOfSubTuples: Dict[str, "RestfulSubTestTuple"] = TupleField()
44
+
45
+
46
+ @addTupleType
47
+ class RestfulSubTestTuple(Tuple):
48
+ """Test Sub Tuple
49
+ This tuple will test if we can have tuples in tuples and still serialise and
50
+ deserialise them.
51
+ """
52
+
53
+ __tupleType__ = "rapui.synerty.RestfulSubTestTuple"
54
+ subInt: int = TupleField()
55
+
56
+
57
+ def _makeRestfultTestTuple():
58
+ tuple_ = RestfulTestTuple()
59
+ tuple_.aBoolTrue = True
60
+ tuple_.aBoolFalse = False
61
+ tuple_.aFloat = 2.56
62
+ tuple_.aInt = 1231231
63
+ tuple_.aIntWithValidator = 50
64
+ tuple_.aString = "test string from 345345345@$#%#$%#$%#$%#"
65
+ tuple_.aList = ["y", 3, True, 3.3]
66
+ tuple_.aDict = {
67
+ "a": "test str",
68
+ "1": 1.234,
69
+ } # Key strings are loaded as unicode
70
+ tuple_.aDictOfSubTuples = {}
71
+
72
+ subTuple = RestfulSubTestTuple()
73
+ subTuple.subInt = 2048
74
+ tuple_.aSubTuple = subTuple
75
+
76
+ tuple_.aListOfSubTuples = []
77
+ for x in range(2):
78
+ subTuple = RestfulSubTestTuple()
79
+ subTuple.subInt = x
80
+ tuple_.aListOfSubTuples.append(subTuple)
81
+
82
+ subTuple = RestfulSubTestTuple()
83
+ subTuple.subInt = x + 10
84
+ tuple_.aDictOfSubTuples[str(x)] = subTuple
85
+
86
+ return tuple_
87
+
88
+
89
+ @ddt
90
+ class TupleRestfulTest(unittest.TestCase):
91
+ def setUp(self):
92
+ pass
93
+
94
+ def tearDown(self):
95
+ pass
96
+
97
+ def _testSerialisation(self, origTuple):
98
+ # To Restful JSON Object
99
+ jsonDict = origTuple.tupleToRestfulJsonDict()
100
+ # Pass it through the JSON object to JSON string conversion
101
+ jsonDict = json.loads(json.dumps(jsonDict))
102
+ # Reconstruct a new Tuple
103
+ deserialisedTuple = (
104
+ RestfulTestTuple().restfulJsonDictToTupleWithValidation(
105
+ jsonDict, RestfulTestTuple
106
+ )
107
+ )
108
+ return deserialisedTuple
109
+
110
+ @data(-1, 110)
111
+ def testIntValidatorInvalid(self, int_):
112
+ # Create tuple
113
+ origTuple = _makeRestfultTestTuple()
114
+ origTuple.aIntWithValidator = int_
115
+ self.assertRaises(ValueError, self._testSerialisation, origTuple)
116
+
117
+ @data(1, 99)
118
+ def testIntValidatorValid(self, int_):
119
+ # Create tuple
120
+ origTuple = _makeRestfultTestTuple()
121
+ origTuple.aIntWithValidator = int_
122
+ self.assertEqual(
123
+ self._testSerialisation(origTuple).aIntWithValidator, int_
124
+ )
125
+
126
+ def testValidatorPass(self):
127
+ # Create tuple
128
+ origTuple = _makeRestfultTestTuple()
129
+
130
+ deserialisedTuple = self._testSerialisation(origTuple)
131
+
132
+ self.assertEqual(TupleHash(origTuple), TupleHash(origTuple))
133
+ self.assertEqual(
134
+ TupleHash(deserialisedTuple), TupleHash(deserialisedTuple)
135
+ )
136
+ self.assertEqual(
137
+ TupleHash(origTuple),
138
+ TupleHash(deserialisedTuple),
139
+ "Tuple serialise -> deserialise error",
140
+ )
@@ -0,0 +1,105 @@
1
+ """
2
+ * Created by Synerty Pty Ltd
3
+ *
4
+ * This software is open source, the MIT license applies.
5
+ *
6
+ * Website : http://www.synerty.com
7
+ * Support : support@synerty.com
8
+ """
9
+ import json
10
+ from typing import Dict, Optional, Union, Type
11
+
12
+ from vortex.Tuple import Tuple, addTupleType
13
+
14
+
15
+ class InvalidTupleSelectorNameException(Exception):
16
+ pass
17
+
18
+
19
+ @addTupleType
20
+ class TupleSelector(Tuple):
21
+ __tupleType__ = "vortex.TupleSelector"
22
+ __slots__ = ["name", "selector"]
23
+
24
+ # name: str = TupleField(comment="The tuple name this selector is for")
25
+ # selector: Dict[str, Any] = TupleField(comment="The values to select")
26
+
27
+ def __init__(
28
+ self,
29
+ name: Optional[Union[str, Type[Tuple], Tuple]] = None,
30
+ selector: Optional[Dict] = None,
31
+ ) -> None:
32
+ Tuple.__init__(self)
33
+ self.name = self.nameFromTuple(name)
34
+ self.selector = selector if selector else {}
35
+
36
+ def __eq__(self, y):
37
+ return self.toJsonStr() == y.toJsonStr()
38
+
39
+ def __hash__(self):
40
+ return hash(self.toJsonStr())
41
+
42
+ # noinspection PyMethodMayBeStatic
43
+ @classmethod
44
+ def nameFromTuple(
45
+ cls, nameOrTuple: Optional[Union[str, Type[Tuple], Tuple]]
46
+ ) -> Optional[str]:
47
+ # When the TupleSelector is reconstructed / deserialised, it's constructed with
48
+ # no arguments
49
+ if nameOrTuple is None:
50
+ return None
51
+
52
+ if isinstance(nameOrTuple, str):
53
+ name = nameOrTuple
54
+
55
+ elif isinstance(nameOrTuple, Tuple):
56
+ name = nameOrTuple.tupleType()
57
+
58
+ elif issubclass(nameOrTuple, Tuple):
59
+ name = nameOrTuple.tupleType()
60
+
61
+ else:
62
+ raise Exception(
63
+ "Argument should be of type Union[str, Type[Tuple], Tuple]"
64
+ )
65
+
66
+ if name == TupleSelector.tupleName():
67
+ raise InvalidTupleSelectorNameException(
68
+ "We've found the name of TupleSelector.tupleType(),"
69
+ "which means we've been passed a TupleSelector."
70
+ )
71
+
72
+ return name
73
+
74
+ def isForTuple(
75
+ self, nameOrTuple: Optional[Union[str, Type[Tuple], Tuple]]
76
+ ) -> bool:
77
+ return self.name == self.nameFromTuple(nameOrTuple)
78
+
79
+ def toJsonStr(self) -> str:
80
+ """To Json Str
81
+
82
+ This method dumps the c{TupleSelector} data to a json string.
83
+
84
+ It sorts the dict keys and
85
+ """
86
+ fieldJsonDict = self.toJsonField(self.selector)
87
+ return json.dumps(
88
+ {"name": self.name, "selector": fieldJsonDict}, sort_keys=True
89
+ )
90
+
91
+ @classmethod
92
+ def fromJsonStr(cls, jsonStr: str) -> "TupleSelector":
93
+ """From Json Str
94
+
95
+ This method creates a new c{TupleSelector} from the ordered json string dumped
96
+ from .toJsonStr
97
+
98
+ """
99
+ data = json.loads(jsonStr)
100
+ newTs = TupleSelector(name=data["name"], selector={})
101
+ newTs.selector = newTs.fromJsonField(data["selector"])
102
+ return newTs
103
+
104
+ def __repr__(self):
105
+ return self.toJsonStr()
vortex/TupleTest.py ADDED
@@ -0,0 +1,127 @@
1
+ """
2
+ * Created by Synerty Pty Ltd
3
+ *
4
+ * This software is open source, the MIT license applies.
5
+ *
6
+ * Website : http://www.synerty.com
7
+ * Support : support@synerty.com
8
+ """
9
+
10
+ import datetime
11
+ import json
12
+
13
+ from twisted.trial import unittest
14
+
15
+ from vortex.TestTuple import TestSubTuple, TestTuple
16
+ from vortex.Tuple import TupleHash
17
+
18
+
19
+ def makeTupleA():
20
+ tuple_ = TestTuple()
21
+ tuple_.aBoolTrue = True
22
+ tuple_.aBoolFalse = False
23
+ tuple_.aDate = datetime.datetime(2010, 4, 7, 2, 33, 19, 666)
24
+ tuple_.aFloat = 2.56
25
+ tuple_.aInt = 1231231
26
+ tuple_.aString = "test string from 345345345@$#%#$%#$%#$%#"
27
+ tuple_.aSet = ["x", 2, False] # Sets are restored as Lists
28
+ tuple_.aList = ["y", 3, True, 3.3]
29
+ tuple_.aDict = {
30
+ "a": "test str", # Key strings are loaded as unicode
31
+ 1: 1.234,
32
+ }
33
+
34
+ subTuple = TestSubTuple()
35
+ subTuple.subInt = 2048
36
+ tuple_.aSubTuple = subTuple
37
+ #
38
+ tuple_.aListOfSubTuples = []
39
+ for x in range(2):
40
+ subTuple = TestSubTuple()
41
+ subTuple.subInt = x
42
+ tuple_.aListOfSubTuples.append(subTuple)
43
+
44
+ return tuple_
45
+
46
+
47
+ class TuplePyTest(unittest.TestCase):
48
+ PERFORMANCE_ITERATIONS = 10000
49
+
50
+ def setUp(self):
51
+ pass
52
+
53
+ def tearDown(self):
54
+ pass
55
+
56
+ def testTupleToFromJson(self):
57
+ # Create tuple
58
+ origTuple = makeTupleA()
59
+
60
+ # To Json
61
+ jsonDictStr = json.dumps(origTuple.toJsonDict())
62
+ deserialisedTuple = TestTuple().fromJsonDict(json.loads(jsonDictStr))
63
+ # print xmlStr
64
+
65
+ self.assertEqual(TupleHash(origTuple), TupleHash(origTuple))
66
+ self.assertEqual(
67
+ TupleHash(deserialisedTuple), TupleHash(deserialisedTuple)
68
+ )
69
+
70
+ # print TupleHash(origTuple)._key()
71
+ # print TupleHash(deserialisedTuple)._key()
72
+
73
+ self.assertEqual(
74
+ TupleHash(origTuple),
75
+ TupleHash(deserialisedTuple),
76
+ "Tuple serialise -> deserialise error",
77
+ )
78
+
79
+ def testTupleToFromJsonPerformanceMulti(self):
80
+ for _ in range(self.PERFORMANCE_ITERATIONS):
81
+ origTuple = makeTupleA()
82
+ jsonDictStr = json.dumps(origTuple.toJsonDict())
83
+ TestTuple().fromJsonDict(json.loads(jsonDictStr))
84
+
85
+ def testTupleToFromJsonPerformanceSingle(self):
86
+ origTuple = makeTupleA()
87
+ origTuple.aListOfSubTuples = [
88
+ makeTupleA() for _ in range(self.PERFORMANCE_ITERATIONS)
89
+ ]
90
+ jsonDictStr = json.dumps(origTuple.toJsonDict())
91
+ TestTuple().fromJsonDict(json.loads(jsonDictStr))
92
+
93
+ def testTupleHash(self):
94
+ hashA1 = TupleHash(makeTupleA())
95
+ hashA2 = TupleHash(makeTupleA())
96
+ print("hashA1 = %s" % hashA1.__hash__())
97
+ print("hashA2 = %s" % hashA2.__hash__())
98
+
99
+ hashB1 = TupleHash(makeTupleA())
100
+ hashB1.tupl.aString = "Not the same as the others"
101
+ print("hashB1 = %s" % hashB1.__hash__())
102
+
103
+ hashA1.__hash__()
104
+ self.assertTrue(
105
+ hashA1.__hash__() == hashA1.__hash__(),
106
+ "TupleHash A1.__hash__() == A1.__hash__()",
107
+ )
108
+
109
+ self.assertTrue(hashA1 == hashA2, "TupleHash __eq__ fail, A1 == A2")
110
+ self.assertFalse(hashA1 != hashA2, "TupleHash __ne__ fail, A1 != A2")
111
+ self.assertFalse(hashA1 == hashB1, "TupleHash __eq__ fail, A1 == B1")
112
+ self.assertTrue(hashA1 != hashB1, "TupleHash __ne__ fail, A1 != B1")
113
+
114
+ self.assertTrue(
115
+ hashA1 in {hashA2: None}, "TupleHash in fail, A1 in {A2:None}"
116
+ )
117
+ self.assertFalse(
118
+ hashA1 not in {hashA2: None},
119
+ "TupleHash in fail, A1 not in {A2:None}",
120
+ )
121
+ self.assertTrue(
122
+ hashA1 not in {hashB1: None},
123
+ "TupleHash in fail, A1 not in {B1:None}",
124
+ )
125
+ self.assertFalse(
126
+ hashA1 in {hashB1: None}, "TupleHash in fail, A1 in {B1:None}"
127
+ )
vortex/VortexABC.py ADDED
@@ -0,0 +1,55 @@
1
+ from abc import ABCMeta, abstractmethod
2
+ from typing import Optional, Union, Callable, List
3
+
4
+ from twisted.internet.defer import Deferred
5
+
6
+ from vortex.PayloadEnvelope import VortexMsgList
7
+
8
+ SendVortexMsgResponseCallable = Callable[
9
+ [Union[VortexMsgList, bytes], int], Deferred
10
+ ]
11
+
12
+
13
+ class VortexInfo:
14
+ """Vortex Info
15
+
16
+ This class stores details about the end of a vortex.
17
+ """
18
+
19
+ def __init__(self, name, uuid):
20
+ self.name, self.uuid = name, uuid
21
+
22
+ def __repr__(self):
23
+ return "VortexInfo, Name=%s, UUID=%s" % (self.name, self.uuid)
24
+
25
+
26
+ class VortexABC(metaclass=ABCMeta):
27
+ @property
28
+ @abstractmethod
29
+ def localVortexInfo(self) -> VortexInfo:
30
+ pass
31
+
32
+ @property
33
+ @abstractmethod
34
+ def remoteVortexInfo(self) -> List[VortexInfo]:
35
+ pass
36
+
37
+ @property
38
+ @abstractmethod
39
+ def requiresBase64Encoding(self) -> bool:
40
+ pass
41
+
42
+ @abstractmethod
43
+ def sendVortexMsg(
44
+ self,
45
+ vortexMsgs: Union[VortexMsgList, bytes],
46
+ vortexUuid: Optional[str] = None,
47
+ ):
48
+ """Send Vortex Msg
49
+
50
+ Sends the vortex message to any conencted clients with vortexUuid.
51
+ Or broadcast it to all connected vortex clients if it's None
52
+
53
+ :param vortexMsgs: The vortex message(s) to send
54
+ :param vortexUuid: The vortexUuid of the client to send to.
55
+ """