Merge from trunk
[plcapi.git] / trunk / PLC / Methods / system / methodSignature.py
diff --git a/trunk/PLC/Methods/system/methodSignature.py b/trunk/PLC/Methods/system/methodSignature.py
new file mode 100644 (file)
index 0000000..4b049a1
--- /dev/null
@@ -0,0 +1,60 @@
+from PLC.Parameter import Parameter, Mixed
+from PLC.Method import Method, xmlrpc_type
+
+class methodSignature(Method):
+    """
+    Returns an array of known signatures (an array of arrays) for the
+    method name passed. If no signatures are known, returns a
+    none-array (test for type != array to detect missing signature).
+    """
+
+    roles = []
+    accepts = [Parameter(str, "Method name")]
+    returns = [Parameter([str], "Method signature")]
+
+    def __init__(self, api):
+        Method.__init__(self, api)
+        self.name = "system.methodSignature"
+
+    def possible_signatures(self, signature, arg):
+        """
+        Return a list of the possible new signatures given a current
+        signature and the next argument.
+        """
+
+        if isinstance(arg, Mixed):
+            arg_types = [xmlrpc_type(mixed_arg) for mixed_arg in arg]
+        else:
+            arg_types = [xmlrpc_type(arg)]
+
+        return [signature + [arg_type] for arg_type in arg_types]
+
+    def signatures(self, returns, args):
+        """
+        Returns a list of possible signatures given a return value and
+        a set of arguments.
+        """
+
+        signatures = [[xmlrpc_type(returns)]]
+
+        for arg in args:
+            # Create lists of possible new signatures for each current
+            # signature. Reduce the list of lists back down to a
+            # single list.
+            signatures = reduce(lambda a, b: a + b,
+                                [self.possible_signatures(signature, arg) \
+                                 for signature in signatures])
+
+        return signatures
+
+    def call(self, method):
+        function = self.api.callable(method)
+        (min_args, max_args, defaults) = function.args()
+
+        signatures = []
+
+        assert len(max_args) >= len(min_args)
+        for num_args in range(len(min_args), len(max_args) + 1):
+            signatures += self.signatures(function.returns, function.accepts[:num_args])
+
+        return signatures