2525
2626class Param (object ):
2727 """
28- A param with self-contained documentation and optionally default value .
28+ A param with self-contained documentation.
2929 """
3030
31- def __init__ (self , parent , name , doc , defaultValue = None ):
32- if not isinstance (parent , Identifiable ):
33- raise ValueError ("Parent must be identifiable but got type %s." % type (parent ).__name__ )
31+ def __init__ (self , parent , name , doc ):
32+ if not isinstance (parent , Params ):
33+ raise ValueError ("Parent must be a Params but got type %s." % type (parent ).__name__ )
3434 self .parent = parent
3535 self .name = str (name )
3636 self .doc = str (doc )
37- self .defaultValue = defaultValue
3837
3938 def __str__ (self ):
40- return str (self .parent ) + "- " + self .name
39+ return str (self .parent ) + "__ " + self .name
4140
4241 def __repr__ (self ):
43- return "Param(parent=%r, name=%r, doc=%r, defaultValue=%r)" % \
44- (self .parent , self .name , self .doc , self .defaultValue )
42+ return "Param(parent=%r, name=%r, doc=%r)" % (self .parent , self .name , self .doc )
4543
4644
4745class Params (Identifiable ):
@@ -52,26 +50,128 @@ class Params(Identifiable):
5250
5351 __metaclass__ = ABCMeta
5452
55- def __init__ (self ):
56- super (Params , self ).__init__ ()
57- #: embedded param map
58- self .paramMap = {}
53+ #: internal param map for user-supplied values param map
54+ paramMap = {}
55+
56+ #: internal param map for default values
57+ defaultParamMap = {}
5958
6059 @property
6160 def params (self ):
6261 """
63- Returns all params. The default implementation uses
64- :py:func:`dir` to get all attributes of type
62+ Returns all params ordered by name . The default implementation
63+ uses :py:func:`dir` to get all attributes of type
6564 :py:class:`Param`.
6665 """
6766 return filter (lambda attr : isinstance (attr , Param ),
6867 [getattr (self , x ) for x in dir (self ) if x != "params" ])
6968
70- def _merge_params (self , params ):
71- paramMap = self .paramMap .copy ()
72- paramMap .update (params )
69+ def _explain (self , param ):
70+ """
71+ Explains a single param and returns its name, doc, and optional
72+ default value and user-supplied value in a string.
73+ """
74+ param = self ._resolveParam (param )
75+ values = []
76+ if self .isDefined (param ):
77+ if param in self .defaultParamMap :
78+ values .append ("default: %s" % self .defaultParamMap [param ])
79+ if param in self .paramMap :
80+ values .append ("current: %s" % self .paramMap [param ])
81+ else :
82+ values .append ("undefined" )
83+ valueStr = "(" + ", " .join (values ) + ")"
84+ return "%s: %s %s" % (param .name , param .doc , valueStr )
85+
86+ def explainParams (self ):
87+ """
88+ Returns the documentation of all params with their optionally
89+ default values and user-supplied values.
90+ """
91+ return "\n " .join ([self ._explain (param ) for param in self .params ])
92+
93+ def getParam (self , paramName ):
94+ """
95+ Gets a param by its name.
96+ """
97+ param = getattr (self , paramName )
98+ if isinstance (param , Param ):
99+ return param
100+ else :
101+ raise ValueError ("Cannot find param with name %s." % paramName )
102+
103+ def isSet (self , param ):
104+ """
105+ Checks whether a param is explicitly set by user.
106+ """
107+ param = self ._resolveParam (param )
108+ return param in self .paramMap
109+
110+ def hasDefault (self , param ):
111+ """
112+ Checks whether a param has a default value.
113+ """
114+ param = self ._resolveParam (param )
115+ return param in self .defaultParamMap
116+
117+ def isDefined (self , param ):
118+ """
119+ Checks whether a param is explicitly set by user or has a default value.
120+ """
121+ return self .isSet (param ) or self .hasDefault (param )
122+
123+ def getOrDefault (self , param ):
124+ """
125+ Gets the value of a param in the user-supplied param map or its
126+ default value. Raises an error if either is set.
127+ """
128+ if isinstance (param , Param ):
129+ if param in self .paramMap :
130+ return self .paramMap [param ]
131+ else :
132+ return self .defaultParamMap [param ]
133+ elif isinstance (param , str ):
134+ return self .getOrDefault (self .getParam (param ))
135+ else :
136+ raise KeyError ("Cannot recognize %r as a param." % param )
137+
138+ def extractParamMap (self , extraParamMap = {}):
139+ """
140+ Extracts the embedded default param values and user-supplied
141+ values, and then merges them with extra values from input into
142+ a flat param map, where the latter value is used if there exist
143+ conflicts, i.e., with ordering: default param values <
144+ user-supplied values < extraParamMap.
145+ :param extraParamMap: extra param values
146+ :return: merged param map
147+ """
148+ paramMap = self .defaultParamMap .copy ()
149+ paramMap .update (self .paramMap )
150+ paramMap .update (extraParamMap )
73151 return paramMap
74152
153+ def _shouldOwn (self , param ):
154+ """
155+ Validates that the input param belongs to this Params instance.
156+ """
157+ if param .parent is not self :
158+ raise ValueError ("Param %r does not belong to %r." % (param , self ))
159+
160+ def _resolveParam (self , param ):
161+ """
162+ Resolves a param and validates the ownership.
163+ :param param: param name or the param instance, which must
164+ belong to this Params instance
165+ :return: resolved param instance
166+ """
167+ if isinstance (param , Param ):
168+ self ._shouldOwn (param )
169+ return param
170+ elif isinstance (param , str ):
171+ return self .getParam (param )
172+ else :
173+ raise ValueError ("Cannot resolve %r as a param." % param )
174+
75175 @staticmethod
76176 def _dummy ():
77177 """
@@ -81,10 +181,18 @@ def _dummy():
81181 dummy .uid = "undefined"
82182 return dummy
83183
84- def _set_params (self , ** kwargs ):
184+ def _set (self , ** kwargs ):
85185 """
86- Sets params.
186+ Sets user-supplied params.
87187 """
88188 for param , value in kwargs .iteritems ():
89189 self .paramMap [getattr (self , param )] = value
90190 return self
191+
192+ def _setDefault (self , ** kwargs ):
193+ """
194+ Sets default params.
195+ """
196+ for param , value in kwargs .iteritems ():
197+ self .defaultParamMap [getattr (self , param )] = value
198+ return self
0 commit comments