do not depend on types.StringTypes anymore
[sfa.git] / sfa / storage / parameter.py
1 #
2 # Shared type definitions
3 #
4 # Mark Huang <mlhuang@cs.princeton.edu>
5 # Copyright (C) 2006 The Trustees of Princeton University
6 #
7
8 from types import NoneType, IntType, LongType, FloatType, DictType, TupleType, ListType
9 from sfa.util.faults import SfaAPIError
10
11 from sfa.util.py23 import StringType
12
13 class Parameter:
14     """
15     Typed value wrapper. Use in accepts and returns to document method
16     parameters. Set the optional and default attributes for
17     sub-parameters (i.e., dict fields).
18     """
19
20     def __init__(self, type, doc = "",
21                  min = None, max = None,
22                  optional = None,
23                  ro = False,
24                  nullok = False):
25         # Basic type of the parameter. Must be a builtin type
26         # that can be marshalled by XML-RPC.
27         self.type = type
28
29         # Documentation string for the parameter
30         self.doc = doc
31
32         # Basic value checking. For numeric types, the minimum and
33         # maximum possible values, inclusive. For string types, the
34         # minimum and maximum possible UTF-8 encoded byte lengths.
35         self.min = min
36         self.max = max
37
38         # Whether the sub-parameter is optional or not. If None,
39         # unknown whether it is optional.
40         self.optional = optional
41
42         # Whether the DB field is read-only.
43         self.ro = ro
44
45         # Whether the DB field can be NULL.
46         self.nullok = nullok
47
48     def type(self):
49         return self.type
50
51     def __repr__(self):
52         return repr(self.type)
53
54 class Mixed(tuple):
55     """
56     A list (technically, a tuple) of types. Use in accepts and returns
57     to document method parameters that may return mixed types.
58     """
59
60     def __new__(cls, *types):
61         return tuple.__new__(cls, types)
62
63
64 def python_type(arg):
65     """
66     Returns the Python type of the specified argument, which may be a
67     Python type, a typed value, or a Parameter.
68     """
69
70     if isinstance(arg, Parameter):
71         arg = arg.type
72
73     if isinstance(arg, type):
74         return arg
75     else:
76         return type(arg)
77
78 def xmlrpc_type(arg):
79     """
80     Returns the XML-RPC type of the specified argument, which may be a
81     Python type, a typed value, or a Parameter.
82     """
83
84     arg_type = python_type(arg)
85
86     if arg_type == NoneType:
87         return "nil"
88     elif arg_type == IntType or arg_type == LongType:
89         return "int"
90     elif arg_type == bool:
91         return "boolean"
92     elif arg_type == FloatType:
93         return "double"
94     elif issubclass(arg_type, StringType):
95         return "string"
96     elif arg_type == ListType or arg_type == TupleType:
97         return "array"
98     elif arg_type == DictType:
99         return "struct"
100     elif arg_type == Mixed:
101         # Not really an XML-RPC type but return "mixed" for
102         # documentation purposes.
103         return "mixed"
104     else:
105         raise SfaAPIError("XML-RPC cannot marshal %s objects" % arg_type)