From fd78cbaf22650c3061368684859925f58c005620 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 27 May 2008 10:12:07 +0300 Subject: First commit in gsoc,reusing public method validation in func_module --- func/minion/modules/func_module.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 7d476dc..693d808 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -58,8 +58,7 @@ class FuncModule(object): """ handlers = {} for attr in dir(self): - if inspect.ismethod(getattr(self, attr)) and attr[0] != '_' and \ - attr != 'register_rpc': + if self.__is_public_valid_method(attr): handlers[attr] = getattr(self, attr) return handlers @@ -74,3 +73,10 @@ class FuncModule(object): def __module_description(self): return self.description + + def __is_public_valid_method(self,attr): + if inspect.ismethod(getattr(self, attr)) and attr[0] != '_' and\ + attr != 'register_rpc': + return True + return False + -- cgit From 5ee76c4ff83c18d9dfbcd677a6e9eb5d9c02d254 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 27 May 2008 10:50:09 +0300 Subject: im a real git lame :) the creation of the new method for arg gettter --- func/minion/modules/func_module.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 693d808..16f6681 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -79,4 +79,13 @@ class FuncModule(object): attr != 'register_rpc': return True return False - + + def __get_method_args(self,meth_name): + """ + Gives a list of arguments for particular given + method_name + + @param meth_name: the name of the method + @retun : list or None + """ + pass -- cgit From fa76ae6a01f8740f831c400cccbb3cc744bfca40 Mon Sep 17 00:00:00 2001 From: makkalot Date: Tue, 27 May 2008 11:00:43 +0300 Subject: thanks god we dont use svn everyone would see what silly things im doing :) --- func/minion/modules/func_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 16f6681..203b321 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -88,4 +88,4 @@ class FuncModule(object): @param meth_name: the name of the method @retun : list or None """ - pass + return None -- cgit From 7b9276ccd4958dc98099421a52278ccdaccbadb7 Mon Sep 17 00:00:00 2001 From: makkalot Date: Tue, 27 May 2008 13:22:06 +0300 Subject: adding get_method_args for the minion part --- func/minion/modules/func_module.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 203b321..fd592c7 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -34,7 +34,8 @@ class FuncModule(object): "module_version" : self.__module_version, "module_api_version" : self.__module_api_version, "module_description" : self.__module_description, - "list_methods" : self.__list_methods + "list_methods" : self.__list_methods, + "get_method_args" : self.__get_method_args, } def __init_log(self): @@ -88,4 +89,24 @@ class FuncModule(object): @param meth_name: the name of the method @retun : list or None """ - return None + if not self.__is_public_valid_method(name): + return {} + + arg_names = inspect.getargspec(getattr(self,name)) + #arg_names[0] is argument names + #arg_names[1] is *arg + #arg_names[2] is **kwarg + #arg_names[3] are defaults + + name_dict =[other_args for other_args in arg_names[1:3] if other_args] + arg_names = arg_names[0] or [] + + #if we have self lets remove it + for rem in arg_names: + if rem=="self": + arg_names.remove(rem) + break + + final_dict={} + final_dict[name]=arg_names+name_dict + return final_dict -- cgit From 2c4817f1ee0f80ad4aae080099994fcec41a529b Mon Sep 17 00:00:00 2001 From: makkalot Date: Tue, 27 May 2008 13:38:12 +0300 Subject: does the arg comes with in a tuple --- func/minion/modules/func_module.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index fd592c7..98d7266 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -89,6 +89,9 @@ class FuncModule(object): @param meth_name: the name of the method @retun : list or None """ + #is it a tuple ? + meth_name = method_name[0] + if not self.__is_public_valid_method(name): return {} -- cgit From 6bb831d276d22649ca80a0fb46f272596f8f81dc Mon Sep 17 00:00:00 2001 From: makkalot Date: Tue, 27 May 2008 14:19:21 +0300 Subject: testing ... --- func/minion/modules/func_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 98d7266..14fdbfe 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -90,7 +90,7 @@ class FuncModule(object): @retun : list or None """ #is it a tuple ? - meth_name = method_name[0] + #meth_name = meth_name[0] if not self.__is_public_valid_method(name): return {} -- cgit From d50ecd9085106d753232ceb54ba41155775cdd67 Mon Sep 17 00:00:00 2001 From: makkalot Date: Tue, 27 May 2008 14:23:46 +0300 Subject: i should take a break --- func/minion/modules/func_module.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 14fdbfe..56fd171 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -81,16 +81,15 @@ class FuncModule(object): return True return False - def __get_method_args(self,meth_name): + def __get_method_args(self,name): """ Gives a list of arguments for particular given method_name - @param meth_name: the name of the method + @param name: the name of the method @retun : list or None """ #is it a tuple ? - #meth_name = meth_name[0] if not self.__is_public_valid_method(name): return {} -- cgit From e3c15b13bf30494451170fd69bfc227272f8eab1 Mon Sep 17 00:00:00 2001 From: makkalot Date: Tue, 27 May 2008 14:39:12 +0300 Subject: we dont need the base one actually (self.__base_methods) --- func/minion/modules/func_module.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 56fd171..d05af66 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -87,13 +87,16 @@ class FuncModule(object): method_name @param name: the name of the method - @retun : list or None + @retun : dict(name:[arg1,arg2...]) or {} """ - #is it a tuple ? - + if not self.__is_public_valid_method(name): return {} + #we dont need them actually + if name in self.__base_methods.keys(): + return {} + arg_names = inspect.getargspec(getattr(self,name)) #arg_names[0] is argument names #arg_names[1] is *arg -- cgit From ce08177132f46d8ae0fa636feaa19f157482afa5 Mon Sep 17 00:00:00 2001 From: makkalot Date: Tue, 27 May 2008 14:47:14 +0300 Subject: sometimes fails if there is no attr like that fixed --- func/minion/modules/func_module.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index d05af66..b13d3ac 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -89,12 +89,15 @@ class FuncModule(object): @param name: the name of the method @retun : dict(name:[arg1,arg2...]) or {} """ + #we dont need them actually + if name in self.__base_methods.keys(): + return {} - if not self.__is_public_valid_method(name): + #tests showed that sometimes happens + if not hasattr(self,name): return {} - #we dont need them actually - if name in self.__base_methods.keys(): + if not self.__is_public_valid_method(name): return {} arg_names = inspect.getargspec(getattr(self,name)) -- cgit From e9d4417179b6c164257794b89ec5da6d853f7d45 Mon Sep 17 00:00:00 2001 From: makkalot Date: Tue, 27 May 2008 15:45:07 +0300 Subject: the unittest for get_method_args it passes the system module test hacky like other members like it we should implement them ... --- func/minion/modules/func_module.py | 1 + test/unittest/test_client.py | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index b13d3ac..21ec3ea 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -90,6 +90,7 @@ class FuncModule(object): @retun : dict(name:[arg1,arg2...]) or {} """ #we dont need them actually + if name in self.__base_methods.keys(): return {} diff --git a/test/unittest/test_client.py b/test/unittest/test_client.py index 578dd90..bae9eab 100644 --- a/test/unittest/test_client.py +++ b/test/unittest/test_client.py @@ -46,6 +46,14 @@ class BaseTest: result = mod.list_methods() self.assert_on_fault(result) + def test_module_get_method_args(self): + mod = getattr(self.overlord,self.module) + result = mod.list_methods() + + for meth in result.values()[0]: + arg_result=mod.get_method_args(meth) + self.assert_on_fault(arg_result) + def test_module_inventory(self): mod = getattr(self.overlord, self.module) result = mod.list_methods() @@ -70,6 +78,7 @@ class BaseTest: test_module_description.intro = True test_module_list_methods.intro = True test_module_inventory.intro = True + test_module_get_method_args.intro = True class TestTest(BaseTest): module = "test" @@ -381,6 +390,8 @@ class TestSystem(BaseTest): def test_module_description(self): pass + def test_module_get_method_args(self): + pass #import time -- cgit From 7159496b5ded2459669fb73744bb3d397c06461e Mon Sep 17 00:00:00 2001 From: makkalot Date: Fri, 30 May 2008 22:57:21 +0300 Subject: new branch new life creating new branch until i merge my stuff to master to no mess with other ready code --- func/minion/modules/func_arg.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 func/minion/modules/func_arg.py diff --git a/func/minion/modules/func_arg.py b/func/minion/modules/func_arg.py new file mode 100644 index 0000000..e69de29 -- cgit From 4357afa7740a407f035e824cfd3bea61a06cefa7 Mon Sep 17 00:00:00 2001 From: makkalot Date: Fri, 30 May 2008 23:56:49 +0300 Subject: add the minion_arg_validator module to code base it is kind fo API what can be assigned and etc --- func/minion/modules/func_arg.py | 140 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/func/minion/modules/func_arg.py b/func/minion/modules/func_arg.py index e69de29..ae6db16 100644 --- a/func/minion/modules/func_arg.py +++ b/func/minion/modules/func_arg.py @@ -0,0 +1,140 @@ +## +## Copyright 2007, Red Hat, Inc +## see AUTHORS +## +## This software may be freely redistributed under the terms of the GNU +## general public license. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +## + +class ArgCompatibility(object): + """ + That class is going to test if the module that was created by module + writer if he/she obeys to the rules we put before + """ + + #these are the common options can be used with all types + __common_options = ('optional','default','description') + + #basic types has types also + __basic_types={ + 'range':(), + 'min':0, + 'max':0, + 'optional':False, + 'description':'', + 'options':(), + 'min_length':0, + 'max_length':0, + 'validator':'', + 'type':'', + 'default':None #its type is unknown + } + + def __init__(self,get_args_result): + """ + The constructor initilized by the get_method_args() + @param : get_args_result : The dict with all method related info + """ + self.__args_to_check = get_args_result + + #what options does each of the basic_types have : + self.__valid_args={ + 'int':('range','min','max'), + 'string':('options','min_length','max_length','validator'), + 'boolean':(), + 'float':(), + 'hash':('validator'), + 'iterable':('validator'), + } + + + def _is_type_options_compatible(self,argument_dict): + """ + Checks the argument_dict's options and looks inside + self.__valid_args to see if the used option is there + + @param : argument_dict : current argument to check + @return : True of raises IncompatibleTypesException + + """ + #did module writer add a key 'type' + if not argument_dict.has_key('type') or not self.__valid_args.has_key(argument_dict['type']): + raise IncompatibleTypesException("%s is not in valid options"%argument_dict['type']) + + # we will use it everytime so not make lookups + the_type = argument_dict['type'] + from itertools import chain + + for key,value in argument_dict.iteritems(): + + if key == "type": + continue + if key not in chain(self.__valid_args[the_type],self.__common_options): + raise IncompatibleTypesException("There is no option like %s in %s"%(key,the_type)) + + return True + + + def _is_basic_types_compatible(self,type_dict): + """ + Validates that if the types that were submitted with + get_method_args were compatible with our format above + in __basic_types + + @param : type_dict : The type to examine + @return : True or raise IncompatibleTypesException Exception + """ + for key,value in type_dict.iteritems(): + + #do we have that type + if not self.__basic_types.has_key(key): + raise IncompatibleTypesException("%s not in the basic_types"%key) + + #if type matches and dont match default + if key!='default' and type(value)!=type(self.__basic_types[key]): + raise IncompatibleTypesException("%s should be %s"%(key,self.__basic_types[key])) + + return True + + + def validate_all(self): + """ + Validates the output for minion module's + get_method_args method + + @return : True or raise IncompatibleTypesException Exception + """ + + for method in self.__args_to_check.iterkeys(): + for argument in self.__args_to_check[method].itervalues(): + self._is_basic_types_compatible(argument) + self._is_type_options_compatible(argument) + + +###The Exception classes here + + +class IncompatibleTypesException(Exception): + """ + Raised when we assign some values that breaksour rules + @see ArgCompatibility class for allowe situations + """ + def __init__(self, value=None): + Exception.__init__(self) + self.value = value + def __str__(self): + return "%s" %(self.value,) + +class NonExistingMethodRegistered(IncompatibleTypesException): + """ + That Exception is raised when a non existent module is + tried to be registerd we shouldnt allow that + """ + pass + + + -- cgit From 15fc492fdb83a1176c658d4ca1277b1d556be787 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sat, 31 May 2008 01:13:33 +0300 Subject: teh unittest for that module --- test/unittest/test_func_arg.py | 65 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 test/unittest/test_func_arg.py diff --git a/test/unittest/test_func_arg.py b/test/unittest/test_func_arg.py new file mode 100644 index 0000000..adee9f0 --- /dev/null +++ b/test/unittest/test_func_arg.py @@ -0,0 +1,65 @@ +## +## Copyright 2007, Red Hat, Inc +## see AUTHORS +## +## This software may be freely redistributed under the terms of the GNU +## general public license. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +## + +#tester module for ArgCompatibility +from func.minion.modules.func_arg import ArgCompatibility + +class ArgCompatibilityTest: + + def setUp(self): + #create the simple object + ac = ArgCompatibility(self.dummy_arg_getter()) + print self.dummy_arg_getter() + + def dummy_arg_getter(self): + """ + A simple method to test the stuff we have written for + arg compatiblity. I just return a dict with proper stuff + """ + return { + 'hifunc':{ + + 'app':{ + 'type':'int', + 'range':(0,100), + 'optional':False, + 'default' : 12 + }, + + 'platform':{ + 'type':'string', + 'min_length':50, + 'max_length':100, + 'options':('fedora8','fedora9','some_other'),'description':"Hey im a fedora fan" + }, + + 'is_independent':{ + 'type':'boolean', + 'default' :False, + 'description':'Are you independent ?' + }, + + 'some_string':{ + 'type':'string', + 'validato': "^[a-zA-Z]$",} # validator is a re string for those whoo need better validation... + + } + } + + def test_arg_compatibility(self): + """ + Simple test + """ + result = self.ac.validate_all() + #self.assert_on_fault(result) + assert result == False + -- cgit From 9f5f7cc9357f975c2415b3b0826eeee54be74c05 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sat, 31 May 2008 01:15:18 +0300 Subject: the actual test unit test but doesnt work properly continue tomorrow --- func/minion/modules/func_arg.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/func/minion/modules/func_arg.py b/func/minion/modules/func_arg.py index ae6db16..4d87e06 100644 --- a/func/minion/modules/func_arg.py +++ b/func/minion/modules/func_arg.py @@ -67,7 +67,7 @@ class ArgCompatibility(object): # we will use it everytime so not make lookups the_type = argument_dict['type'] - from itertools import chain + from itertools import chain #may i use chain ? for key,value in argument_dict.iteritems(): @@ -114,6 +114,8 @@ class ArgCompatibility(object): self._is_basic_types_compatible(argument) self._is_type_options_compatible(argument) + return True + ###The Exception classes here -- cgit From 77f20e5f743535c8935eeb2c2d7a750700d108d9 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sat, 31 May 2008 11:48:52 +0300 Subject: unittest fixed and should add more and more to make it perfect :) --- test/unittest/test_func_arg.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/test/unittest/test_func_arg.py b/test/unittest/test_func_arg.py index adee9f0..daec346 100644 --- a/test/unittest/test_func_arg.py +++ b/test/unittest/test_func_arg.py @@ -13,17 +13,25 @@ #tester module for ArgCompatibility from func.minion.modules.func_arg import ArgCompatibility -class ArgCompatibilityTest: +class TestArgCompatibility: def setUp(self): #create the simple object - ac = ArgCompatibility(self.dummy_arg_getter()) - print self.dummy_arg_getter() + self.ac = ArgCompatibility(self.dummy_arg_getter()) + + def test_arg_compatibility(self): + """ + Testing the method argument compatiblity + """ + result = self.ac.validate_all() + #self.assert_on_fault(result) + assert result == True def dummy_arg_getter(self): """ A simple method to test the stuff we have written for arg compatiblity. I just return a dict with proper stuff + Should more an more tests here to see if didnt miss something """ return { 'hifunc':{ @@ -50,16 +58,9 @@ class ArgCompatibilityTest: 'some_string':{ 'type':'string', - 'validato': "^[a-zA-Z]$",} # validator is a re string for those whoo need better validation... + 'validator': "^[a-zA-Z]$",} # validator is a re string for those whoo need better validation... } } - def test_arg_compatibility(self): - """ - Simple test - """ - result = self.ac.validate_all() - #self.assert_on_fault(result) - assert result == False - + -- cgit From 12706048cee60b7d39c03104a8b288e5fa6368ee Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 1 Jun 2008 12:16:57 +0300 Subject: minor changes in arg module, discovered in unittests ,testing is cool :) --- func/minion/modules/func_arg.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/func/minion/modules/func_arg.py b/func/minion/modules/func_arg.py index 4d87e06..95cc000 100644 --- a/func/minion/modules/func_arg.py +++ b/func/minion/modules/func_arg.py @@ -13,7 +13,7 @@ class ArgCompatibility(object): """ That class is going to test if the module that was created by module - writer if he/she obeys to the rules we put before + writer if he/she obeys to the rules we put here """ #these are the common options can be used with all types @@ -36,19 +36,19 @@ class ArgCompatibility(object): def __init__(self,get_args_result): """ - The constructor initilized by the get_method_args() + The constructor initilized by the get_method_args()(the dict to test) @param : get_args_result : The dict with all method related info """ self.__args_to_check = get_args_result #what options does each of the basic_types have : self.__valid_args={ - 'int':('range','min','max'), - 'string':('options','min_length','max_length','validator'), + 'int':('range','min','max',), + 'string':('options','min_length','max_length','validator',), 'boolean':(), 'float':(), - 'hash':('validator'), - 'iterable':('validator'), + 'hash':('validator',), + 'iterable':('validator',), } @@ -123,7 +123,7 @@ class ArgCompatibility(object): class IncompatibleTypesException(Exception): """ Raised when we assign some values that breaksour rules - @see ArgCompatibility class for allowe situations + @see ArgCompatibility class for allowed situations """ def __init__(self, value=None): Exception.__init__(self) -- cgit From 771267e7b441e4f730ea41880268c298ef01d771 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 1 Jun 2008 12:17:28 +0300 Subject: minor changes not so importants --- test/unittest/test_func_arg.py | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/test/unittest/test_func_arg.py b/test/unittest/test_func_arg.py index daec346..c1a1e37 100644 --- a/test/unittest/test_func_arg.py +++ b/test/unittest/test_func_arg.py @@ -24,7 +24,6 @@ class TestArgCompatibility: Testing the method argument compatiblity """ result = self.ac.validate_all() - #self.assert_on_fault(result) assert result == True def dummy_arg_getter(self): @@ -45,21 +44,47 @@ class TestArgCompatibility: 'platform':{ 'type':'string', - 'min_length':50, + 'min_length':5, 'max_length':100, - 'options':('fedora8','fedora9','some_other'),'description':"Hey im a fedora fan" + 'options':('fedora8','fedora9','some_other'),'description':"Hey im a fedora fan", + 'default':'fedora8', }, 'is_independent':{ 'type':'boolean', 'default' :False, - 'description':'Are you independent ?' + 'description':'Are you independent ?', + 'optional':False }, 'some_string':{ 'type':'string', - 'validator': "^[a-zA-Z]$",} # validator is a re string for those whoo need better validation... - + 'validator': "^[a-zA-Z]$", + 'description':'String to be validated', + 'default':'makkalot', + 'optional':False}, # validator is a re string for those whoo need better validation,so when we have options there is no need to use validator and reverse is True + #to define also a float we dont need it actually but maybe useful for the UI stuff. + 'some_float':{ + 'type':'float', + 'description':'The float point value', + 'default':33.44, + 'optional':False + }, + + 'some_iterable':{ + 'type':'iterable', + 'description':'The value and description for *arg', + 'optional':True, #that is where it makes sense + 'validator':'^[0-9]+$',#maybe useful to say it is to be a number for example + }, + + 'some_hash':{ + 'type':'hash', + 'description':'The value and description for **kwarg', + 'optional':True, #of course it is, + 'validator':'^[a-z]*$',#only for values not keys + + } } } -- cgit From aeb784f6958b39d16e4ae879a68e35962b053a76 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 1 Jun 2008 13:07:16 +0300 Subject: reorganizing the func_arg to be able to get method arguments, small pushes are cool --- func/minion/modules/func_arg.py | 8 ++++++++ func/minion/modules/func_module.py | 24 +++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/func/minion/modules/func_arg.py b/func/minion/modules/func_arg.py index 95cc000..27beb93 100644 --- a/func/minion/modules/func_arg.py +++ b/func/minion/modules/func_arg.py @@ -138,5 +138,13 @@ class NonExistingMethodRegistered(IncompatibleTypesException): """ pass +class UnregisteredMethodArgument(IncompatibleTypesException): + """ + That exception is to try to remove the errors that user may + do during method registration process. If a argument is missed + to be registerted in the method that exception is Raised! + """ + pass + diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 21ec3ea..edb554c 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -15,7 +15,7 @@ import inspect from func import logger from func.config import read_config from func.commonconfig import FuncdConfig - +from func.minion.modules.func_arg import * #the arg getter stuff class FuncModule(object): @@ -81,16 +81,26 @@ class FuncModule(object): return True return False - def __get_method_args(self,name): + def get_method_args(self,name): """ - Gives a list of arguments for particular given - method_name + Gets arguments with their formats according to ArgCompatibility + class' rules. - @param name: the name of the method + @param :name The name of the method + @return : dict with args or Raise Exception if something wrong + happens + """ + pass + + def __is_all_args_registered(self,name): + """ + Checks if module writer has made some mistakes about + argument registering + + @param name: the name of the method with arguments registered in it @retun : dict(name:[arg1,arg2...]) or {} """ - #we dont need them actually - + #FIXME tobe rewritten if name in self.__base_methods.keys(): return {} -- cgit From 4a274173556d7366604160abbfeb57b51b4eb53b Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 1 Jun 2008 13:37:51 +0300 Subject: get_method args implemented also has backward support --- func/minion/modules/func_module.py | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index edb554c..e2a47c3 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -81,16 +81,45 @@ class FuncModule(object): return True return False - def get_method_args(self,name): + def __get_method_args(self): """ Gets arguments with their formats according to ArgCompatibility class' rules. - @param :name The name of the method @return : dict with args or Raise Exception if something wrong happens """ - pass + tmp_arg_dict = self.__register_method_args() + + #if it is not implemeted then return empty stuff + if not tmp_arg_dict: + return {} + + #or go ahead + #see if user tried to register an not implemented method :) + for method in tmp_arg_dict.keys(): + if not hasattr(self,method): + raise NonExistingMethodRegistered("%s is not in %s "%(method,self.__class__.__name__)) + + #create argument validation instance + self.arg_comp = ArgCompatibility(tmp_arg_dict) + #see if the options that were used are OK.. + self.arg_comp.validate_all() + + return tmp_arg_dict + + def __register_method_args(self): + """ + That is the method where users should override in their + modules according to be able to send their method arguments + to the Overlord. If they dont have it nothing breaks + just that one in the base class is called + + @return : empty {} + """ + + # to know they didnt implement it + return {} def __is_all_args_registered(self,name): """ -- cgit From e8f7ed14ea4c1f82869253735cb861ac319ca4df Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 1 Jun 2008 19:05:03 +0300 Subject: some testing commits --- func/minion/modules/func_module.py | 1 - test/unittest/test_client.py | 10 ++++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index e2a47c3..813dcf2 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -95,7 +95,6 @@ class FuncModule(object): if not tmp_arg_dict: return {} - #or go ahead #see if user tried to register an not implemented method :) for method in tmp_arg_dict.keys(): if not hasattr(self,method): diff --git a/test/unittest/test_client.py b/test/unittest/test_client.py index bae9eab..9628973 100644 --- a/test/unittest/test_client.py +++ b/test/unittest/test_client.py @@ -14,7 +14,8 @@ import socket class BaseTest: # assume we are talking to localhost # th = socket.gethostname() - th = socket.getfqdn() + maho ="hard.evlan.com" + th = socket.getfqdn(maho) nforks=1 async=False @@ -48,11 +49,8 @@ class BaseTest: def test_module_get_method_args(self): mod = getattr(self.overlord,self.module) - result = mod.list_methods() - - for meth in result.values()[0]: - arg_result=mod.get_method_args(meth) - self.assert_on_fault(arg_result) + arg_result=mod.get_method_args() + self.assert_on_fault(arg_result) def test_module_inventory(self): mod = getattr(self.overlord, self.module) -- cgit From 7b339cfc592e4243e84a1ecd3f5673021d2b73a0 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 1 Jun 2008 19:13:27 +0300 Subject: a dummy test --- func/minion/modules/func_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 813dcf2..cb2970c 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -118,7 +118,7 @@ class FuncModule(object): """ # to know they didnt implement it - return {} + return {'hey':'how'} def __is_all_args_registered(self,name): """ -- cgit From a5b1aac806dad3691a191fe9e13ba07d3f888b2f Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 1 Jun 2008 19:17:33 +0300 Subject: move file to parent dir --- func/minion/func_arg.py | 150 ++++++++++++++++++++++++++++++++++++++++ func/minion/modules/func_arg.py | 150 ---------------------------------------- 2 files changed, 150 insertions(+), 150 deletions(-) create mode 100644 func/minion/func_arg.py delete mode 100644 func/minion/modules/func_arg.py diff --git a/func/minion/func_arg.py b/func/minion/func_arg.py new file mode 100644 index 0000000..27beb93 --- /dev/null +++ b/func/minion/func_arg.py @@ -0,0 +1,150 @@ +## +## Copyright 2007, Red Hat, Inc +## see AUTHORS +## +## This software may be freely redistributed under the terms of the GNU +## general public license. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +## + +class ArgCompatibility(object): + """ + That class is going to test if the module that was created by module + writer if he/she obeys to the rules we put here + """ + + #these are the common options can be used with all types + __common_options = ('optional','default','description') + + #basic types has types also + __basic_types={ + 'range':(), + 'min':0, + 'max':0, + 'optional':False, + 'description':'', + 'options':(), + 'min_length':0, + 'max_length':0, + 'validator':'', + 'type':'', + 'default':None #its type is unknown + } + + def __init__(self,get_args_result): + """ + The constructor initilized by the get_method_args()(the dict to test) + @param : get_args_result : The dict with all method related info + """ + self.__args_to_check = get_args_result + + #what options does each of the basic_types have : + self.__valid_args={ + 'int':('range','min','max',), + 'string':('options','min_length','max_length','validator',), + 'boolean':(), + 'float':(), + 'hash':('validator',), + 'iterable':('validator',), + } + + + def _is_type_options_compatible(self,argument_dict): + """ + Checks the argument_dict's options and looks inside + self.__valid_args to see if the used option is there + + @param : argument_dict : current argument to check + @return : True of raises IncompatibleTypesException + + """ + #did module writer add a key 'type' + if not argument_dict.has_key('type') or not self.__valid_args.has_key(argument_dict['type']): + raise IncompatibleTypesException("%s is not in valid options"%argument_dict['type']) + + # we will use it everytime so not make lookups + the_type = argument_dict['type'] + from itertools import chain #may i use chain ? + + for key,value in argument_dict.iteritems(): + + if key == "type": + continue + if key not in chain(self.__valid_args[the_type],self.__common_options): + raise IncompatibleTypesException("There is no option like %s in %s"%(key,the_type)) + + return True + + + def _is_basic_types_compatible(self,type_dict): + """ + Validates that if the types that were submitted with + get_method_args were compatible with our format above + in __basic_types + + @param : type_dict : The type to examine + @return : True or raise IncompatibleTypesException Exception + """ + for key,value in type_dict.iteritems(): + + #do we have that type + if not self.__basic_types.has_key(key): + raise IncompatibleTypesException("%s not in the basic_types"%key) + + #if type matches and dont match default + if key!='default' and type(value)!=type(self.__basic_types[key]): + raise IncompatibleTypesException("%s should be %s"%(key,self.__basic_types[key])) + + return True + + + def validate_all(self): + """ + Validates the output for minion module's + get_method_args method + + @return : True or raise IncompatibleTypesException Exception + """ + + for method in self.__args_to_check.iterkeys(): + for argument in self.__args_to_check[method].itervalues(): + self._is_basic_types_compatible(argument) + self._is_type_options_compatible(argument) + + return True + + +###The Exception classes here + + +class IncompatibleTypesException(Exception): + """ + Raised when we assign some values that breaksour rules + @see ArgCompatibility class for allowed situations + """ + def __init__(self, value=None): + Exception.__init__(self) + self.value = value + def __str__(self): + return "%s" %(self.value,) + +class NonExistingMethodRegistered(IncompatibleTypesException): + """ + That Exception is raised when a non existent module is + tried to be registerd we shouldnt allow that + """ + pass + +class UnregisteredMethodArgument(IncompatibleTypesException): + """ + That exception is to try to remove the errors that user may + do during method registration process. If a argument is missed + to be registerted in the method that exception is Raised! + """ + pass + + + diff --git a/func/minion/modules/func_arg.py b/func/minion/modules/func_arg.py deleted file mode 100644 index 27beb93..0000000 --- a/func/minion/modules/func_arg.py +++ /dev/null @@ -1,150 +0,0 @@ -## -## Copyright 2007, Red Hat, Inc -## see AUTHORS -## -## This software may be freely redistributed under the terms of the GNU -## general public license. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -## - -class ArgCompatibility(object): - """ - That class is going to test if the module that was created by module - writer if he/she obeys to the rules we put here - """ - - #these are the common options can be used with all types - __common_options = ('optional','default','description') - - #basic types has types also - __basic_types={ - 'range':(), - 'min':0, - 'max':0, - 'optional':False, - 'description':'', - 'options':(), - 'min_length':0, - 'max_length':0, - 'validator':'', - 'type':'', - 'default':None #its type is unknown - } - - def __init__(self,get_args_result): - """ - The constructor initilized by the get_method_args()(the dict to test) - @param : get_args_result : The dict with all method related info - """ - self.__args_to_check = get_args_result - - #what options does each of the basic_types have : - self.__valid_args={ - 'int':('range','min','max',), - 'string':('options','min_length','max_length','validator',), - 'boolean':(), - 'float':(), - 'hash':('validator',), - 'iterable':('validator',), - } - - - def _is_type_options_compatible(self,argument_dict): - """ - Checks the argument_dict's options and looks inside - self.__valid_args to see if the used option is there - - @param : argument_dict : current argument to check - @return : True of raises IncompatibleTypesException - - """ - #did module writer add a key 'type' - if not argument_dict.has_key('type') or not self.__valid_args.has_key(argument_dict['type']): - raise IncompatibleTypesException("%s is not in valid options"%argument_dict['type']) - - # we will use it everytime so not make lookups - the_type = argument_dict['type'] - from itertools import chain #may i use chain ? - - for key,value in argument_dict.iteritems(): - - if key == "type": - continue - if key not in chain(self.__valid_args[the_type],self.__common_options): - raise IncompatibleTypesException("There is no option like %s in %s"%(key,the_type)) - - return True - - - def _is_basic_types_compatible(self,type_dict): - """ - Validates that if the types that were submitted with - get_method_args were compatible with our format above - in __basic_types - - @param : type_dict : The type to examine - @return : True or raise IncompatibleTypesException Exception - """ - for key,value in type_dict.iteritems(): - - #do we have that type - if not self.__basic_types.has_key(key): - raise IncompatibleTypesException("%s not in the basic_types"%key) - - #if type matches and dont match default - if key!='default' and type(value)!=type(self.__basic_types[key]): - raise IncompatibleTypesException("%s should be %s"%(key,self.__basic_types[key])) - - return True - - - def validate_all(self): - """ - Validates the output for minion module's - get_method_args method - - @return : True or raise IncompatibleTypesException Exception - """ - - for method in self.__args_to_check.iterkeys(): - for argument in self.__args_to_check[method].itervalues(): - self._is_basic_types_compatible(argument) - self._is_type_options_compatible(argument) - - return True - - -###The Exception classes here - - -class IncompatibleTypesException(Exception): - """ - Raised when we assign some values that breaksour rules - @see ArgCompatibility class for allowed situations - """ - def __init__(self, value=None): - Exception.__init__(self) - self.value = value - def __str__(self): - return "%s" %(self.value,) - -class NonExistingMethodRegistered(IncompatibleTypesException): - """ - That Exception is raised when a non existent module is - tried to be registerd we shouldnt allow that - """ - pass - -class UnregisteredMethodArgument(IncompatibleTypesException): - """ - That exception is to try to remove the errors that user may - do during method registration process. If a argument is missed - to be registerted in the method that exception is Raised! - """ - pass - - - -- cgit From 5ff04c7b52d9f273bb307aa03346e05466d5e5b4 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 1 Jun 2008 19:19:10 +0300 Subject: fix the import not to fail --- func/minion/modules/func_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index cb2970c..07b5443 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -15,7 +15,7 @@ import inspect from func import logger from func.config import read_config from func.commonconfig import FuncdConfig -from func.minion.modules.func_arg import * #the arg getter stuff +from func.minion.func_arg import * #the arg getter stuff class FuncModule(object): -- cgit From c1caf860b5bcf68ac3bd542f792626b115324566 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 1 Jun 2008 20:42:48 +0300 Subject: remove that dummy line im a complete git lame really --- func/minion/modules/func_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 07b5443..5c9eb03 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -118,7 +118,7 @@ class FuncModule(object): """ # to know they didnt implement it - return {'hey':'how'} + return {} def __is_all_args_registered(self,name): """ -- cgit From 7388fc3e74711c5a9a788e96a02d7daa063ba9d4 Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 2 Jun 2008 19:29:23 +0300 Subject: remove the old version of the get_method_arguments --- func/minion/modules/func_module.py | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 5c9eb03..cfd7438 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -120,40 +120,3 @@ class FuncModule(object): # to know they didnt implement it return {} - def __is_all_args_registered(self,name): - """ - Checks if module writer has made some mistakes about - argument registering - - @param name: the name of the method with arguments registered in it - @retun : dict(name:[arg1,arg2...]) or {} - """ - #FIXME tobe rewritten - if name in self.__base_methods.keys(): - return {} - - #tests showed that sometimes happens - if not hasattr(self,name): - return {} - - if not self.__is_public_valid_method(name): - return {} - - arg_names = inspect.getargspec(getattr(self,name)) - #arg_names[0] is argument names - #arg_names[1] is *arg - #arg_names[2] is **kwarg - #arg_names[3] are defaults - - name_dict =[other_args for other_args in arg_names[1:3] if other_args] - arg_names = arg_names[0] or [] - - #if we have self lets remove it - for rem in arg_names: - if rem=="self": - arg_names.remove(rem) - break - - final_dict={} - final_dict[name]=arg_names+name_dict - return final_dict -- cgit From 871aae17edf1f0e45ad8075016bde1ba5f68e969 Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 2 Jun 2008 19:30:12 +0300 Subject: implement the current options for service module to see if it works --- func/minion/modules/service.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/func/minion/modules/service.py b/func/minion/modules/service.py index 062aea5..a4e8bea 100644 --- a/func/minion/modules/service.py +++ b/func/minion/modules/service.py @@ -86,3 +86,29 @@ class Service(func_module.FuncModule): tokens = line.split() results.append((tokens[0], tokens[-1].replace("...",""))) return results + + def __register_method_args(self): + """ + Implementing the argument getter + """ + + #service_name options they are same so use only one + service_name = { + 'type':'string', + 'description':'The name of the running services', + 'validator':'^[a-z]+$'} + + return { + 'get_running':{}, + 'get_enabled':{}, + 'inventory':{}, + 'status':{ + 'service_name':service_name, + }, + 'reload':{'service_name':service_name}, + 'restart':{'service_name':service_name}, + 'stop':{'service_name':service_name}, + 'start':{'service_name':service_name}, + + + } -- cgit From 1b4b73ed260c72ebeb0168c4a649e4f02eeb8dde Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 2 Jun 2008 19:56:48 +0300 Subject: arghh we can not use private methods so make public that register thing --- func/minion/modules/func_module.py | 6 +++--- func/minion/modules/service.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index cfd7438..724a27b 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -77,7 +77,7 @@ class FuncModule(object): def __is_public_valid_method(self,attr): if inspect.ismethod(getattr(self, attr)) and attr[0] != '_' and\ - attr != 'register_rpc': + attr != 'register_rpc' and attr!='register_method_args': return True return False @@ -89,7 +89,7 @@ class FuncModule(object): @return : dict with args or Raise Exception if something wrong happens """ - tmp_arg_dict = self.__register_method_args() + tmp_arg_dict = self.register_method_args() #if it is not implemeted then return empty stuff if not tmp_arg_dict: @@ -107,7 +107,7 @@ class FuncModule(object): return tmp_arg_dict - def __register_method_args(self): + def register_method_args(self): """ That is the method where users should override in their modules according to be able to send their method arguments diff --git a/func/minion/modules/service.py b/func/minion/modules/service.py index a4e8bea..e615e1b 100644 --- a/func/minion/modules/service.py +++ b/func/minion/modules/service.py @@ -87,7 +87,7 @@ class Service(func_module.FuncModule): results.append((tokens[0], tokens[-1].replace("...",""))) return results - def __register_method_args(self): + def register_method_args(self): """ Implementing the argument getter """ -- cgit From 2de89d9a6180c4fa6ca8a523913fd583f18c35fc Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 2 Jun 2008 20:48:29 +0300 Subject: the test tobe from localhost --- test/unittest/test_client.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/unittest/test_client.py b/test/unittest/test_client.py index 9628973..c92224e 100644 --- a/test/unittest/test_client.py +++ b/test/unittest/test_client.py @@ -14,8 +14,7 @@ import socket class BaseTest: # assume we are talking to localhost # th = socket.gethostname() - maho ="hard.evlan.com" - th = socket.getfqdn(maho) + th = socket.getfqdn() nforks=1 async=False -- cgit From 82a7c1936fd75bab52d735fef86325f66dd4f7e5 Mon Sep 17 00:00:00 2001 From: makkalot Date: Tue, 3 Jun 2008 20:34:06 +0300 Subject: fixing import error thanks to alikins :) --- test/unittest/test_func_arg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unittest/test_func_arg.py b/test/unittest/test_func_arg.py index c1a1e37..bb7a5e2 100644 --- a/test/unittest/test_func_arg.py +++ b/test/unittest/test_func_arg.py @@ -11,7 +11,7 @@ ## #tester module for ArgCompatibility -from func.minion.modules.func_arg import ArgCompatibility +from func.minion.func_arg import ArgCompatibility class TestArgCompatibility: -- cgit From 18a872de604eaeefff7603fd889a8f7baf8fc94e Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 8 Jun 2008 15:03:24 +0300 Subject: adding method_name:{args:{},description:..} structure to get_method_args and fixing some stupid bugs --- func/minion/func_arg.py | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/func/minion/func_arg.py b/func/minion/func_arg.py index 27beb93..b8a01fa 100644 --- a/func/minion/func_arg.py +++ b/func/minion/func_arg.py @@ -18,15 +18,16 @@ class ArgCompatibility(object): #these are the common options can be used with all types __common_options = ('optional','default','description') + __method_options = ('description','args') #making method declarations more generic like method_name:{'args':{...},'description':"bla bla"} #basic types has types also __basic_types={ - 'range':(), + 'range':[1,], 'min':0, 'max':0, 'optional':False, 'description':'', - 'options':(), + 'options':[1,], 'min_length':0, 'max_length':0, 'validator':'', @@ -54,7 +55,7 @@ class ArgCompatibility(object): def _is_type_options_compatible(self,argument_dict): """ - Checks the argument_dict's options and looks inside + Checks the method's argument_dict's options and looks inside self.__valid_args to see if the used option is there @param : argument_dict : current argument to check @@ -63,7 +64,7 @@ class ArgCompatibility(object): """ #did module writer add a key 'type' if not argument_dict.has_key('type') or not self.__valid_args.has_key(argument_dict['type']): - raise IncompatibleTypesException("%s is not in valid options"%argument_dict['type']) + raise IncompatibleTypesException("%s is not in valid options,possible ones are :%s"%(argument_dict['type'],str(self.__valid_args))) # we will use it everytime so not make lookups the_type = argument_dict['type'] @@ -88,6 +89,7 @@ class ArgCompatibility(object): @param : type_dict : The type to examine @return : True or raise IncompatibleTypesException Exception """ + #print "The structure we got is %s:"%(type_dict) for key,value in type_dict.iteritems(): #do we have that type @@ -95,24 +97,42 @@ class ArgCompatibility(object): raise IncompatibleTypesException("%s not in the basic_types"%key) #if type matches and dont match default + #print "The key: %s its value %s and type %s"%(key,value,type(value)) if key!='default' and type(value)!=type(self.__basic_types[key]): - raise IncompatibleTypesException("%s should be %s"%(key,self.__basic_types[key])) + raise IncompatibleTypesException("The %s keyword should be in that type %s"%(key,type(self.__basic_types[key]))) - return True + return True def validate_all(self): """ Validates the output for minion module's get_method_args method - + + The structure that is going to be validated is in that format : + + { + method_name1 : {'args':{...}, + 'description':"wowo"}, + method_name12 : {...} + } + @return : True or raise IncompatibleTypesException Exception """ - + for method in self.__args_to_check.iterkeys(): - for argument in self.__args_to_check[method].itervalues(): - self._is_basic_types_compatible(argument) - self._is_type_options_compatible(argument) + #here we got args or description part + #check if user did submit something not in the __method_options + + for method_option in self.__args_to_check[method].iterkeys(): + if method_option not in self.__method_options: + raise IncompatibleTypesException("There is no option for method_name like %s,possible ones are : %s"%(method_option,str(self.__method_options))) + #check what is inside the args + if method_option == "args": + for argument in self.__args_to_check[method][method_option].itervalues(): + #print argument + self._is_basic_types_compatible(argument) + self._is_type_options_compatible(argument) return True -- cgit From 218579808049d8739f2be29b88a96a515034b8d5 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 8 Jun 2008 15:11:10 +0300 Subject: changing get_method_args tests --- test/unittest/test_func_arg.py | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/test/unittest/test_func_arg.py b/test/unittest/test_func_arg.py index bb7a5e2..35f09c9 100644 --- a/test/unittest/test_func_arg.py +++ b/test/unittest/test_func_arg.py @@ -25,6 +25,25 @@ class TestArgCompatibility: """ result = self.ac.validate_all() assert result == True + + self.ac = ArgCompatibility(self.dummy_no_getter()) + result = self.ac.validate_all() + assert result == True + + self.ac = ArgCompatibility(self.dummy_empty_args()) + result = self.ac.validate_all() + assert result == True + + def dummy_no_getter(self): + return {} + + def dummy_empty_args(self): + return{ + 'myfunc':{ + 'args':{}, + 'description':'Cool methods here' + } + } def dummy_arg_getter(self): """ @@ -34,19 +53,21 @@ class TestArgCompatibility: """ return { 'hifunc':{ - + + 'args':{ 'app':{ 'type':'int', - 'range':(0,100), + 'range':[0,100], 'optional':False, 'default' : 12 }, 'platform':{ 'type':'string', - 'min_length':5, - 'max_length':100, - 'options':('fedora8','fedora9','some_other'),'description':"Hey im a fedora fan", + 'min_length':4, + 'max_length':33, + 'options':["fedora","redhat","ubuntu"], + 'description':"Hey im a fedora fan", 'default':'fedora8', }, @@ -80,12 +101,16 @@ class TestArgCompatibility: 'some_hash':{ 'type':'hash', - 'description':'The value and description for **kwarg', + 'description':"Dummy desc here", 'optional':True, #of course it is, - 'validator':'^[a-z]*$',#only for values not keys + 'validator':"^[a-z]*$",#only for values not keys } + }, + 'description':"The dummy method description", } } + + -- cgit From 00d991fc56a21460ff4989d1b50fbb28788fe3e3 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 8 Jun 2008 15:23:54 +0300 Subject: update the service module according to new stuff --- func/minion/modules/service.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/func/minion/modules/service.py b/func/minion/modules/service.py index e615e1b..5052615 100644 --- a/func/minion/modules/service.py +++ b/func/minion/modules/service.py @@ -99,16 +99,18 @@ class Service(func_module.FuncModule): 'validator':'^[a-z]+$'} return { - 'get_running':{}, - 'get_enabled':{}, - 'inventory':{}, - 'status':{ + 'get_running':{'args':{}}, + 'get_enabled':{'args':{}}, + 'inventory':{'args':{}}, + 'status':{'args':{ 'service_name':service_name, }, - 'reload':{'service_name':service_name}, - 'restart':{'service_name':service_name}, - 'stop':{'service_name':service_name}, - 'start':{'service_name':service_name}, + 'description':'Getting the status of the service_name' + }, + 'reload':{'args':{'service_name':service_name}}, + 'restart':{'args':{'service_name':service_name}}, + 'stop':{'args':{'service_name':service_name}}, + 'start':{'args':{'service_name':service_name}}, } -- cgit From e05caff42e95b4926411071200da422aa19e5605 Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 9 Jun 2008 01:00:06 +0300 Subject: change name iterable to list to prevent confusions --- func/minion/func_arg.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/func/minion/func_arg.py b/func/minion/func_arg.py index b8a01fa..4a5ed7e 100644 --- a/func/minion/func_arg.py +++ b/func/minion/func_arg.py @@ -47,9 +47,9 @@ class ArgCompatibility(object): 'int':('range','min','max',), 'string':('options','min_length','max_length','validator',), 'boolean':(), - 'float':(), + 'float':('range','min','max'), 'hash':('validator',), - 'iterable':('validator',), + 'list':('validator',), } -- cgit From 944165dba4a7fba8564b0581db0c7e5633b0cd50 Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 9 Jun 2008 01:01:03 +0300 Subject: changing test for new one list keyword --- test/unittest/test_func_arg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unittest/test_func_arg.py b/test/unittest/test_func_arg.py index 35f09c9..1b9102c 100644 --- a/test/unittest/test_func_arg.py +++ b/test/unittest/test_func_arg.py @@ -93,7 +93,7 @@ class TestArgCompatibility: }, 'some_iterable':{ - 'type':'iterable', + 'type':'list', 'description':'The value and description for *arg', 'optional':True, #that is where it makes sense 'validator':'^[0-9]+$',#maybe useful to say it is to be a number for example -- cgit From 838da241f7011a95dec1ae2082804f4ad5d73701 Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 9 Jun 2008 01:03:47 +0300 Subject: test for widget automation the first one --- funcweb/funcweb/tests/test_widget_automation.py | 89 +++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 funcweb/funcweb/tests/test_widget_automation.py diff --git a/funcweb/funcweb/tests/test_widget_automation.py b/funcweb/funcweb/tests/test_widget_automation.py new file mode 100644 index 0000000..fb62f2a --- /dev/null +++ b/funcweb/funcweb/tests/test_widget_automation.py @@ -0,0 +1,89 @@ +import unittest +import turbogears +from turbogears import testutil +from funcweb.controllers import Root +import cherrypy + +cherrypy.root = Root() + +class TestWidgetListFactory(unittest.TestCase): + + def setUp(self): + self.widget_factory = WidgetListFactory(self.get_test_default_args()) + + + def tearDown(self): + pass + + def test_default_args(self): + """ + Simple test to see if all arguments are assigned into + input widget objects + """ + compare_with = self.get_test_default_args() + widget_list=self.widget_factory.get_widgetlist() + + for argument_name,argument_options in compare_with: + assert widget_list.has_key(argument) == True + + #because some of them dont have it like boolean + if argument_options.has_key('default'): + assert argument_options['default'] == getattr(widget_list[argument_name],'default') + + #if it is optional it should ne is_required = True + assert not argument_options['optional']== getattr(widget_list[argument_name],'is_required') + + assert argument_options['description']==getattr(widget_list[argument_name],'help_text') + + #that should be enough + + def get_test_default_args(self): + """ + Simple testing case to see if have all the + things working properly ... + """ + return { + 'string_default':{ + 'type':'string', + 'default':'default string', + 'optional':False, + 'description':'default description' + }, + 'int_default':{ + 'type':'int', + 'default':'default int', + 'optional':False, + 'description':'default description' + }, + #no sense to have default + 'boolean_default':{ + 'type':'boolean' + 'optional':False, + 'description':'default description' + }, + 'float_default':{ + 'type':'float' + 'default':'default float', + 'optional':False, + 'description':'default description' + + }, + 'hash_default':{ + 'type':'hash' + 'default':'default hash', + 'optional':False, + 'description':'default description' + + }, + 'list_default':{ + 'type':'list' + 'default':'default list', + 'optional':False, + 'description':'default description' + + } + + } + + def get_test_specialized_case(self): + pass -- cgit From b4fdd76d9f21afc2c8ce5198fcf5761b307d3da2 Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 9 Jun 2008 01:06:22 +0300 Subject: initial design for widget input factory --- funcweb/funcweb/widget_automation.py | 124 +++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 funcweb/funcweb/widget_automation.py diff --git a/funcweb/funcweb/widget_automation.py b/funcweb/funcweb/widget_automation.py new file mode 100644 index 0000000..7fec309 --- /dev/null +++ b/funcweb/funcweb/widget_automation.py @@ -0,0 +1,124 @@ +#the purpose of that module is to make widget automation +#for registered minion modules so we dont hace to write +#that same boring stuff for every added module ! + +from turbogears.widgets.base import Widget,WidgetsList + +class WidgetListFactory(object): + """ + The class is responsible for taking the method arguments + and converting them to the appropriate widget equivalents + + Examples : + """ + #which type matches for which InputWidget + __convert_table={ + 'int':{ + 'default_value':"TextField", + 'range':"SingleSelectField"}, + 'string':{ + 'default_value':"TextField", + 'options':"SingleSelectField"}, + 'boolean':{' + default_value':"CheckBox"}, + 'float':{ + 'default_value':"TextField", + 'range':"SingleSelectField"}, + 'hash':{ + 'default_value':"TextArea"}, + 'list':{ + 'default_value':"TextArea"} + } + + #will contain the input widget created in that class + __widget_list={} + + def __init__(self,argument_dict): + """ + Initiated with argument_dict of a method to return back + a WidgetsList object to be placed into a form object + + @param:argument_dict : The structure we got here is like + {'arg1':{'type':'int'..},'arg2':{'min':111} ...} + """ + + self.__argument_dict = argument_dict + + def __add_general_widget(self): + + #key is the argument_name and the argument are options + for key,argument in self.__argument_dict.iteritems(): + #get the type of the argument + current_type = argument['type'] + + act_special = False #if it has some special parameters + #it should be passed to its specialized method,if it has + #for example options in its key it should be shown as a + #SingleSelectField not a TextFiled + + for type_match in self.__convert_table[current_type].keys(): + if type_match!='default_value' and argument.has_key(type_match): + act_special = True + + print key,argument + + if act_special: + getattr(self,"__add_%s_widget")(argument['type']) #call the appropriate one + else: + temp_object = getattr(widgets,self.__convert_table[current_type]['default_value']) + #add common options to it + self.__add_commons_to_object(temp_object,argument,key) + #add a new entry to final list + self.__widget_list[key]=temp_object + + def __add_commons_to_object(self,object,argument,argument_name): + """ + As it was thought all input widgets have the same + common parameters they take so that method will add + them to instantiated object for ex (TextField) if they + occur into the argument ... + + @param object : instantiated inputwidget object + @param method argument to lookup {type:'int','max':12 ...} + @return :None + """ + #firstly set the name of the argument + setattr(object,"name",argument_name) + + if argument.has_key('default'): + setattr(object,"default",argument["default"]) + if argument.has_key('optional') and argument['optional']: + setattr(object,'is_required',False) + else: + setattr(object,'is_required',True) + if argument.has_key('description'): + setattr(object,'help_text',argument['description']) + + + def __add_string_widget(self,arg_dict): + print "Called with act special" + pass + + def __add_int_widget(self,arg_dict): + print "Called with act special" + pass + + def __add_boolean_widget(self,arg_dict): + print "Called with act special" + pass + + def __add_hash_widget(self,arg_dict): + print "Called with act special" + pass + + def __add_list_widget(self,arg_dict): + print "Called with act special" + pass + + def get_widgetlist(self): + """ + Return the final list back + """ + #compute the list + self.__add_general_widget() + return self.__widget_list -- cgit From b7ef8e70c0d98f32dc7cbca82904ab216f4a90f7 Mon Sep 17 00:00:00 2001 From: makkalot Date: Tue, 10 Jun 2008 15:52:20 +0300 Subject: removing is_required assignment and fixing some stupid errors --- funcweb/funcweb/widget_automation.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/funcweb/funcweb/widget_automation.py b/funcweb/funcweb/widget_automation.py index 7fec309..de6158e 100644 --- a/funcweb/funcweb/widget_automation.py +++ b/funcweb/funcweb/widget_automation.py @@ -3,6 +3,7 @@ #that same boring stuff for every added module ! from turbogears.widgets.base import Widget,WidgetsList +from turbogears import widgets class WidgetListFactory(object): """ @@ -19,8 +20,8 @@ class WidgetListFactory(object): 'string':{ 'default_value':"TextField", 'options':"SingleSelectField"}, - 'boolean':{' - default_value':"CheckBox"}, + 'boolean':{ + 'default_value':"CheckBox"}, 'float':{ 'default_value':"TextField", 'range':"SingleSelectField"}, @@ -60,16 +61,20 @@ class WidgetListFactory(object): if type_match!='default_value' and argument.has_key(type_match): act_special = True - print key,argument + # print key,argument if act_special: getattr(self,"__add_%s_widget")(argument['type']) #call the appropriate one else: - temp_object = getattr(widgets,self.__convert_table[current_type]['default_value']) + temp_object = getattr(widgets,self.__convert_table[current_type]['default_value'])() #add common options to it self.__add_commons_to_object(temp_object,argument,key) #add a new entry to final list self.__widget_list[key]=temp_object + #print "That have the object :",getattr(self.__widget_list[key],"default") + del temp_object + + #print "That have the object :",getattr(self.__widget_list["list_default"],"default") def __add_commons_to_object(self,object,argument,argument_name): """ @@ -84,13 +89,12 @@ class WidgetListFactory(object): """ #firstly set the name of the argument setattr(object,"name",argument_name) + + #print "The argument name is :",argument_name + #print "The argument options are :",argument if argument.has_key('default'): setattr(object,"default",argument["default"]) - if argument.has_key('optional') and argument['optional']: - setattr(object,'is_required',False) - else: - setattr(object,'is_required',True) if argument.has_key('description'): setattr(object,'help_text',argument['description']) -- cgit From 025c412a18393163746c7ee74887126ab1af285e Mon Sep 17 00:00:00 2001 From: makkalot Date: Tue, 10 Jun 2008 15:52:57 +0300 Subject: changing the tests according to changed stuff --- funcweb/funcweb/tests/test_widget_automation.py | 31 ++++++++++--------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/funcweb/funcweb/tests/test_widget_automation.py b/funcweb/funcweb/tests/test_widget_automation.py index fb62f2a..964df3c 100644 --- a/funcweb/funcweb/tests/test_widget_automation.py +++ b/funcweb/funcweb/tests/test_widget_automation.py @@ -4,6 +4,7 @@ from turbogears import testutil from funcweb.controllers import Root import cherrypy +from funcweb.widget_automation import WidgetListFactory cherrypy.root = Root() class TestWidgetListFactory(unittest.TestCase): @@ -16,32 +17,24 @@ class TestWidgetListFactory(unittest.TestCase): pass def test_default_args(self): - """ - Simple test to see if all arguments are assigned into - input widget objects - """ compare_with = self.get_test_default_args() widget_list=self.widget_factory.get_widgetlist() + + #print "The widget list is like :",widget_list - for argument_name,argument_options in compare_with: - assert widget_list.has_key(argument) == True - + for argument_name,argument_options in compare_with.iteritems(): + assert widget_list.has_key(argument_name) == True + #print "The argument name is :",argument_name #because some of them dont have it like boolean if argument_options.has_key('default'): assert argument_options['default'] == getattr(widget_list[argument_name],'default') - #if it is optional it should ne is_required = True - assert not argument_options['optional']== getattr(widget_list[argument_name],'is_required') - - assert argument_options['description']==getattr(widget_list[argument_name],'help_text') + if argument_options.has_key("description"): + assert argument_options['description']==getattr(widget_list[argument_name],'help_text') #that should be enough def get_test_default_args(self): - """ - Simple testing case to see if have all the - things working properly ... - """ return { 'string_default':{ 'type':'string', @@ -57,26 +50,26 @@ class TestWidgetListFactory(unittest.TestCase): }, #no sense to have default 'boolean_default':{ - 'type':'boolean' + 'type':'boolean', 'optional':False, 'description':'default description' }, 'float_default':{ - 'type':'float' + 'type':'float', 'default':'default float', 'optional':False, 'description':'default description' }, 'hash_default':{ - 'type':'hash' + 'type':'hash', 'default':'default hash', 'optional':False, 'description':'default description' }, 'list_default':{ - 'type':'list' + 'type':'list', 'default':'default list', 'optional':False, 'description':'default description' -- cgit From 94b741de46ba38c19ebcf5df55e8256cd3dc6d02 Mon Sep 17 00:00:00 2001 From: makkalot Date: Thu, 12 Jun 2008 11:20:12 +0300 Subject: adding string dropdown --- funcweb/funcweb/widget_automation.py | 50 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/funcweb/funcweb/widget_automation.py b/funcweb/funcweb/widget_automation.py index de6158e..4d6d665 100644 --- a/funcweb/funcweb/widget_automation.py +++ b/funcweb/funcweb/widget_automation.py @@ -16,7 +16,7 @@ class WidgetListFactory(object): __convert_table={ 'int':{ 'default_value':"TextField", - 'range':"SingleSelectField"}, + }, 'string':{ 'default_value':"TextField", 'options':"SingleSelectField"}, @@ -24,13 +24,12 @@ class WidgetListFactory(object): 'default_value':"CheckBox"}, 'float':{ 'default_value':"TextField", - 'range':"SingleSelectField"}, + }, 'hash':{ 'default_value':"TextArea"}, 'list':{ 'default_value':"TextArea"} } - #will contain the input widget created in that class __widget_list={} @@ -64,7 +63,8 @@ class WidgetListFactory(object): # print key,argument if act_special: - getattr(self,"__add_%s_widget")(argument['type']) #call the appropriate one + #calling for example __add_specialized_string(..) + getattr(self,"_%s__add_specialized_%s"%(self.__class__.__name__,current_type))(argument,key) else: temp_object = getattr(widgets,self.__convert_table[current_type]['default_value'])() #add common options to it @@ -75,6 +75,27 @@ class WidgetListFactory(object): del temp_object #print "That have the object :",getattr(self.__widget_list["list_default"],"default") + + def __add_specialized_string(self,argument,argument_name): + """ + Specialized option adder, called when the type:string is used + with option 'options' so we should create a new SingleSelectField + that one canno be created like others because user should supply options + in the constructor of the SingleSelectField so it becomes a special one + + @param : argument : the argument options, + @param : argument_name : the name of the argument also the name of the widget + @return : Nothing + """ + + #allittle bit difficult to follow but that structure does + #temp_object = SingleSelectField() for example + + temp_object = getattr(widgets,self.__convert_table[argument['type']]['options'])(options = argument['options']) + self.__add_commons_to_object(temp_object,argument,argument_name) + #add a new entry to final list + self.__widget_list[argument_name]=temp_object + del temp_object def __add_commons_to_object(self,object,argument,argument_name): """ @@ -97,28 +118,7 @@ class WidgetListFactory(object): setattr(object,"default",argument["default"]) if argument.has_key('description'): setattr(object,'help_text',argument['description']) - - - def __add_string_widget(self,arg_dict): - print "Called with act special" - pass - - def __add_int_widget(self,arg_dict): - print "Called with act special" - pass - def __add_boolean_widget(self,arg_dict): - print "Called with act special" - pass - - def __add_hash_widget(self,arg_dict): - print "Called with act special" - pass - - def __add_list_widget(self,arg_dict): - print "Called with act special" - pass - def get_widgetlist(self): """ Return the final list back -- cgit From e21ab672adc4076ef3e9068db5420787802556b4 Mon Sep 17 00:00:00 2001 From: makkalot Date: Thu, 12 Jun 2008 11:20:40 +0300 Subject: adding tests for specialized cases --- funcweb/funcweb/tests/test_widget_automation.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/funcweb/funcweb/tests/test_widget_automation.py b/funcweb/funcweb/tests/test_widget_automation.py index 964df3c..0adbc1f 100644 --- a/funcweb/funcweb/tests/test_widget_automation.py +++ b/funcweb/funcweb/tests/test_widget_automation.py @@ -20,7 +20,7 @@ class TestWidgetListFactory(unittest.TestCase): compare_with = self.get_test_default_args() widget_list=self.widget_factory.get_widgetlist() - #print "The widget list is like :",widget_list + print "The widget list is like :",widget_list for argument_name,argument_options in compare_with.iteritems(): assert widget_list.has_key(argument_name) == True @@ -32,6 +32,9 @@ class TestWidgetListFactory(unittest.TestCase): if argument_options.has_key("description"): assert argument_options['description']==getattr(widget_list[argument_name],'help_text') + if argument_options.has_key("options"): + assert argument_options['options'] == getattr(widget_list[argument_name],"options") + #that should be enough def get_test_default_args(self): @@ -74,6 +77,14 @@ class TestWidgetListFactory(unittest.TestCase): 'optional':False, 'description':'default description' + }, + #will be converted to dropdown + 'special_string':{ + 'type':'string', + 'default':'myfirst', + 'options':['myfirst','mysecond','mythird'], + 'optional':False, + 'description':'default dropdown list' } } -- cgit From 588679c610f0f93f40fd2bfa9c6ce01a6223e778 Mon Sep 17 00:00:00 2001 From: makkalot Date: Thu, 12 Jun 2008 19:42:43 +0300 Subject: returning back a WidgetList object --- funcweb/funcweb/tests/test_widget_automation.py | 13 ++++++++++--- funcweb/funcweb/widget_automation.py | 19 ++++++++++++++++++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/funcweb/funcweb/tests/test_widget_automation.py b/funcweb/funcweb/tests/test_widget_automation.py index 0adbc1f..f841c43 100644 --- a/funcweb/funcweb/tests/test_widget_automation.py +++ b/funcweb/funcweb/tests/test_widget_automation.py @@ -20,7 +20,7 @@ class TestWidgetListFactory(unittest.TestCase): compare_with = self.get_test_default_args() widget_list=self.widget_factory.get_widgetlist() - print "The widget list is like :",widget_list + #print "The widget list is like :",widget_list for argument_name,argument_options in compare_with.iteritems(): assert widget_list.has_key(argument_name) == True @@ -36,6 +36,15 @@ class TestWidgetListFactory(unittest.TestCase): assert argument_options['options'] == getattr(widget_list[argument_name],"options") #that should be enough + def test_get_widgetlist_object(self): + compare_with = self.get_test_default_args() + widget_list_object = self.widget_factory.get_widgetlist_object() + + #print widget_list_object + + for argument_name in compare_with.keys(): + assert hasattr(widget_list_object,argument_name) == True + #print getattr(widget_list_object,argument_name) def get_test_default_args(self): return { @@ -89,5 +98,3 @@ class TestWidgetListFactory(unittest.TestCase): } - def get_test_specialized_case(self): - pass diff --git a/funcweb/funcweb/widget_automation.py b/funcweb/funcweb/widget_automation.py index 4d6d665..36d8a5c 100644 --- a/funcweb/funcweb/widget_automation.py +++ b/funcweb/funcweb/widget_automation.py @@ -121,8 +121,25 @@ class WidgetListFactory(object): def get_widgetlist(self): """ - Return the final list back + Return back a dictionay with argument_name : input_widget + pairs. That method may not be called directly,get_widgetlist_object + is better for using in web interface """ #compute the list self.__add_general_widget() return self.__widget_list + + def get_widgetlist_object(self): + """ + Method return back the final widgetlist object + which is turbogears.widgets.WidgetsList + """ + if len(self.__widget_list.keys())==0: + self.__add_general_widget() #not very efficient + + widget_list_object = widgets.WidgetsList() + for name,input_widget in self.__widget_list.iteritems(): + setattr(widget_list_object,name,input_widget) + + #get the object back + return widget_list_object -- cgit From 90b17c280e33a9feeda71962e9f82ef53f774879 Mon Sep 17 00:00:00 2001 From: makkalot Date: Thu, 12 Jun 2008 19:51:39 +0300 Subject: write a TODO to not forget the things please :) --- funcweb/TODO.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 funcweb/TODO.txt diff --git a/funcweb/TODO.txt b/funcweb/TODO.txt new file mode 100644 index 0000000..0eeae7c --- /dev/null +++ b/funcweb/TODO.txt @@ -0,0 +1,17 @@ +Things to be done for funcweb (makkalot) + + ? : not sure + - : not completed + + : completed + / : being implemented + + +Widget Automation for Minion methods : + (+) Creating InputWidgets for method arguments + (+) Creating WidgetList with created InputWidgets + (/) Creating Validators for method arguments + (-)Combining Validators and WidgetList into a RemoteForm + (/) Writing tests for the API + +New Ideas : + -???? -- cgit From 0616b737922449af511bcf918f662c3e4f1c4f35 Mon Sep 17 00:00:00 2001 From: makkalot Date: Thu, 12 Jun 2008 22:20:58 +0300 Subject: adding a RemoteForm automation to our widget factory --- funcweb/funcweb/tests/test_widget_automation.py | 10 ++++-- funcweb/funcweb/widget_automation.py | 47 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/funcweb/funcweb/tests/test_widget_automation.py b/funcweb/funcweb/tests/test_widget_automation.py index f841c43..5a2247d 100644 --- a/funcweb/funcweb/tests/test_widget_automation.py +++ b/funcweb/funcweb/tests/test_widget_automation.py @@ -4,7 +4,7 @@ from turbogears import testutil from funcweb.controllers import Root import cherrypy -from funcweb.widget_automation import WidgetListFactory +from funcweb.widget_automation import WidgetListFactory,RemoteFormAutomation cherrypy.root = Root() class TestWidgetListFactory(unittest.TestCase): @@ -44,7 +44,13 @@ class TestWidgetListFactory(unittest.TestCase): for argument_name in compare_with.keys(): assert hasattr(widget_list_object,argument_name) == True - #print getattr(widget_list_object,argument_name) + #print getattr(widget_list_object,argument_name) + + + def test_remote_form(self): + widget_list_object = self.widget_factory.get_widgetlist_object() + remote_form = RemoteFormAutomation(widget_list_object) + #print remote_form def get_test_default_args(self): return { diff --git a/funcweb/funcweb/widget_automation.py b/funcweb/funcweb/widget_automation.py index 36d8a5c..92ab7ab 100644 --- a/funcweb/funcweb/widget_automation.py +++ b/funcweb/funcweb/widget_automation.py @@ -143,3 +143,50 @@ class WidgetListFactory(object): #get the object back return widget_list_object + +#################################################################################################################### +from turbogears.widgets.base import CoreWD +from turbogears.widgets import RemoteForm +from turbogears import validators, expose + +class RemoteFormAutomation(CoreWD): + """ + Base class for ajaxian Form creation + """ + + name = "Ajaxian Minion Submit Form" + + template = """ +
+ {for_widget.display()} +
+
+
+ """ + + full_class_name = "turbogears.widgets.RemoteForm" + + def __init__(self,generated_fields,*args,**kwarg): + """ + The constructor part same as normal one except + it takes a WidgetsList object into generated_fields + which is generated by WidgetListFactory + """ + #call the master :) + super(RemoteFormAutomation,self).__init__(*args,**kwarg) + self.for_widget = RemoteForm( + fields = generated_fields, + name = "minion_form", + update = "post_data", + before='getElement(\'loading\').innerHTML=\'Submiting form!\';', + on_complete='getElement(\'loading\' ).innerHTML=\'Done!\';', + action = "%s/post_form"%(self.full_class_name) + ) + + def post_form(self,**kw): + """ + Data processing part + """ + return "I got that data from the remote minion form :
%r"%kw + + post_form = expose()(post_form) -- cgit From ec4aac1710a2f040ab51128c3c2c3841b5b29b43 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 00:12:45 +0300 Subject: adding mochikit to funcweb --- funcweb/funcweb/config/app.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/funcweb/funcweb/config/app.cfg b/funcweb/funcweb/config/app.cfg index e691bde..336dc84 100644 --- a/funcweb/funcweb/config/app.cfg +++ b/funcweb/funcweb/config/app.cfg @@ -7,7 +7,8 @@ # The commented out values below are the defaults # VIEW - +#tg.include_widgets = ['turbogears.mochikit'] +tg.mochikit_all = True # which view (template engine) to use if one is not specified in the # template name tg.defaultview = "genshi" -- cgit From 858723f6f4f3763040e02c5e9a2fa692ad97444f Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 00:13:47 +0300 Subject: add controller code to displau automated widgets --- funcweb/funcweb/controllers.py | 47 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/funcweb/funcweb/controllers.py b/funcweb/funcweb/controllers.py index b45d81b..8dba678 100644 --- a/funcweb/funcweb/controllers.py +++ b/funcweb/funcweb/controllers.py @@ -3,11 +3,12 @@ log = logging.getLogger(__name__) from turbogears import controllers, expose, flash, identity, redirect from func.overlord.client import Overlord, Minions +from turbogears import mochikit class Root(controllers.RootController): @expose(template="funcweb.templates.minions") - @identity.require(identity.not_anonymous()) + #@identity.require(identity.not_anonymous()) def minions(self, glob='*'): """ Return a list of our minions that match a given glob """ return dict(minions=Minions(glob).get_all_hosts()) @@ -15,8 +16,8 @@ class Root(controllers.RootController): index = minions # start with our minion view, for now @expose(template="funcweb.templates.minion") - @identity.require(identity.not_anonymous()) - def minion(self, name, module=None, method=None): + #@identity.require(identity.not_anonymous()) + def minion(self, name="*", module=None, method=None): """ Display module or method details for a specific minion. If only the minion name is given, it will display a list of modules @@ -26,6 +27,7 @@ class Root(controllers.RootController): """ fc = Overlord(name) if not module: # list all modules + #just list those who have get_method_args modules = fc.system.list_modules() return dict(modules=modules) else: # a module is specified @@ -39,13 +41,42 @@ class Root(controllers.RootController): @expose(template="funcweb.templates.run") - @identity.require(identity.not_anonymous()) + #@identity.require(identity.not_anonymous()) def run(self, minion="*", module=None, method=None, arguments=''): fc = Overlord(minion) results = getattr(getattr(fc, module), method)(*arguments.split()) cmd = "%s.%s.%s(%s)" % (minion, module, method, arguments) return dict(cmd=cmd, results=results) + + @expose(template="funcweb.templates.method_args") + #@identity.require(identity.not_anonymous()) + def method_display(self,minion="*",module="service",method="reload"): + + fc = Overlord(minion) + method_args = getattr(fc,module).get_method_args() + + if not method_args.values(): + print "Not registered method here" + return dict(minion_form = None) + + print method + the_one = method_args[minion][method]['args'] + if the_one: + + from funcweb.widget_automation import WidgetListFactory,RemoteFormAutomation,RemoteFormFactory + wlist_object = WidgetListFactory(the_one) + wlist_object=wlist_object.get_widgetlist_object() + minion_form =RemoteFormFactory(wlist_object).get_remote_form() + #minion_form = RemoteFormAutomation(wlist_object) + #print minion_form.fields + + #print minion_form + return dict(minion_form=minion_form) + else: + return dict(minion_form = None) + + @expose(template="funcweb.templates.login") def login(self, forward_url=None, previous_url=None, *args, **kw): from cherrypy import request, response @@ -71,6 +102,14 @@ class Root(controllers.RootController): return dict(message=msg, previous_url=previous_url, logging_in=True, original_parameters=request.params, forward_url=forward_url) + + @expose(allow_json=True) + def post_form(self,**kw): + """ + Data processing part + """ + return "I got that data from the remote minion form :
%r"%kw + @expose() def logout(self): -- cgit From 6948a2fcbeba31fff17a1f08381ff103dbe655a2 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 00:24:22 +0300 Subject: some html work to showup method args --- funcweb/funcweb/templates/master.html | 15 ++++++++++----- funcweb/funcweb/templates/method.html | 9 ++++----- funcweb/funcweb/templates/minion.html | 5 +++-- funcweb/funcweb/templates/minions.html | 6 +++--- funcweb/funcweb/templates/module.html | 2 +- funcweb/funcweb/templates/run.html | 5 +++-- 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/funcweb/funcweb/templates/master.html b/funcweb/funcweb/templates/master.html index ab14ca0..33d14f9 100644 --- a/funcweb/funcweb/templates/master.html +++ b/funcweb/funcweb/templates/master.html @@ -9,9 +9,8 @@ + -
+

Func

diff --git a/funcweb/funcweb/templates/method.html b/funcweb/funcweb/templates/method.html index 1f67ce9..af20d86 100644 --- a/funcweb/funcweb/templates/method.html +++ b/funcweb/funcweb/templates/method.html @@ -2,18 +2,17 @@ + +
${minion}.${module}.${method} - -
+ +
-
diff --git a/funcweb/funcweb/templates/minion.html b/funcweb/funcweb/templates/minion.html index f171b00..dcb5c6f 100644 --- a/funcweb/funcweb/templates/minion.html +++ b/funcweb/funcweb/templates/minion.html @@ -2,12 +2,13 @@ + -
+
diff --git a/funcweb/funcweb/templates/minions.html b/funcweb/funcweb/templates/minions.html index 94ccbc1..605080f 100644 --- a/funcweb/funcweb/templates/minions.html +++ b/funcweb/funcweb/templates/minions.html @@ -3,14 +3,14 @@ xmlns:py="http://genshi.edgewall.org/" xmlns:xi="http://www.w3.org/2001/XInclude"> - + -
+
diff --git a/funcweb/funcweb/templates/module.html b/funcweb/funcweb/templates/module.html index 2d433f6..f169007 100644 --- a/funcweb/funcweb/templates/module.html +++ b/funcweb/funcweb/templates/module.html @@ -7,7 +7,7 @@
diff --git a/funcweb/funcweb/templates/run.html b/funcweb/funcweb/templates/run.html index cb17cdd..7ae047b 100644 --- a/funcweb/funcweb/templates/run.html +++ b/funcweb/funcweb/templates/run.html @@ -2,7 +2,8 @@ - - ${results.values()[0]} + + + ${results.values()[0]} -- cgit From 4aeef3391a7a447dffa62b376a47fbf57a041ac5 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 00:25:08 +0300 Subject: better tests --- funcweb/funcweb/tests/test_widget_automation.py | 29 +++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/funcweb/funcweb/tests/test_widget_automation.py b/funcweb/funcweb/tests/test_widget_automation.py index 5a2247d..a81bc1e 100644 --- a/funcweb/funcweb/tests/test_widget_automation.py +++ b/funcweb/funcweb/tests/test_widget_automation.py @@ -4,7 +4,8 @@ from turbogears import testutil from funcweb.controllers import Root import cherrypy -from funcweb.widget_automation import WidgetListFactory,RemoteFormAutomation +from funcweb.widget_automation import WidgetListFactory,RemoteFormAutomation,RemoteFormFactory + cherrypy.root = Root() class TestWidgetListFactory(unittest.TestCase): @@ -42,8 +43,11 @@ class TestWidgetListFactory(unittest.TestCase): #print widget_list_object + all_fields = [getattr(field,"name") for field in widget_list_object] + #print all_fields for argument_name in compare_with.keys(): - assert hasattr(widget_list_object,argument_name) == True + print argument_name + assert argument_name in all_fields #print getattr(widget_list_object,argument_name) @@ -52,6 +56,27 @@ class TestWidgetListFactory(unittest.TestCase): remote_form = RemoteFormAutomation(widget_list_object) #print remote_form + def test_remote_form_factory(self): + from turbogears.view import load_engines + load_engines() + + # WidgetsList object + widget_list_object = self.widget_factory.get_widgetlist_object() + #print widget_list_object + remote_form = RemoteFormFactory(widget_list_object).get_remote_form() + + #it is a key,value dict + widget_list=self.widget_factory.get_widgetlist() + #print widget_list + all_fields = [getattr(field,"name") for field in remote_form.fields] + #print all_fields + #will check if the remote form object hass all the names in it + for argument_name in widget_list.items(): + argument_name in all_fields + + + print remote_form.render() + def get_test_default_args(self): return { 'string_default':{ -- cgit From 4676909acf44c0c2f91eece7ba66fc61b79b1d94 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 00:26:06 +0300 Subject: some fixes in automation code and adding a remoteform factory --- funcweb/funcweb/widget_automation.py | 46 ++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/funcweb/funcweb/widget_automation.py b/funcweb/funcweb/widget_automation.py index 92ab7ab..28f93b9 100644 --- a/funcweb/funcweb/widget_automation.py +++ b/funcweb/funcweb/widget_automation.py @@ -134,15 +134,19 @@ class WidgetListFactory(object): Method return back the final widgetlist object which is turbogears.widgets.WidgetsList """ + + #print self.__widget_list if len(self.__widget_list.keys())==0: self.__add_general_widget() #not very efficient widget_list_object = widgets.WidgetsList() for name,input_widget in self.__widget_list.iteritems(): - setattr(widget_list_object,name,input_widget) + #it is a list indeed + widget_list_object.append(input_widget) #get the object back - return widget_list_object + #print widget_list_object + return widget_list_object #################################################################################################################### from turbogears.widgets.base import CoreWD @@ -158,13 +162,13 @@ class RemoteFormAutomation(CoreWD): template = """
- {for_widget.display()} + ${for_widget.display()}
""" - full_class_name = "turbogears.widgets.RemoteForm" + full_class_name = "funcweb.controllers.Root" def __init__(self,generated_fields,*args,**kwarg): """ @@ -180,7 +184,7 @@ class RemoteFormAutomation(CoreWD): update = "post_data", before='getElement(\'loading\').innerHTML=\'Submiting form!\';', on_complete='getElement(\'loading\' ).innerHTML=\'Done!\';', - action = "%s/post_form"%(self.full_class_name) + action = "/post_form" ) def post_form(self,**kw): @@ -190,3 +194,35 @@ class RemoteFormAutomation(CoreWD): return "I got that data from the remote minion form :
%r"%kw post_form = expose()(post_form) + +#################################################################################################### +class RemoteFormFactory(object): + """ + Gets the WidgetListFactory object + and return back a RemoteForm + """ + #some values that may want to change later + name = 'minion_form' + before='MochiKit.DOM.getElement(\'loading\').innerHTML=\'Submiting form!\';', + on_complete='MochiKit.DOM.getElement(\'loading\' ).innerHTML=\'Done!\';', + update = "post_data" + submit_text = "Send Minion Form" + action = "/post_form" + + def __init__(self,wlist_object): + self.wlist_object = wlist_object + + def get_remote_form(self): + + #print self.wlist_object + + return RemoteForm( + name = self.name, + fields = self.wlist_object, + before = self.before, + on_complete = self.on_complete, + update = self.update, + submit_text = self.submit_text, + action = self.action + ) + -- cgit From 83a9970b426ff334315841b6aa2b91ecb81226dc Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 00:26:53 +0300 Subject: the html form to submit arguments --- funcweb/funcweb/templates/method_args.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 funcweb/funcweb/templates/method_args.html diff --git a/funcweb/funcweb/templates/method_args.html b/funcweb/funcweb/templates/method_args.html new file mode 100644 index 0000000..42946a8 --- /dev/null +++ b/funcweb/funcweb/templates/method_args.html @@ -0,0 +1,12 @@ + + + + +
+ ${ET(minion_form.display(displays_on='genshi'))} +
+ + + -- cgit From 51719e470bba1543c151ba5051e48c419f5fe019 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 12:16:41 +0300 Subject: add link executer --- funcweb/funcweb/widget_automation.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/funcweb/funcweb/widget_automation.py b/funcweb/funcweb/widget_automation.py index 28f93b9..e27d865 100644 --- a/funcweb/funcweb/widget_automation.py +++ b/funcweb/funcweb/widget_automation.py @@ -226,3 +226,28 @@ class RemoteFormFactory(object): action = self.action ) +class RemoteLinkFactory(CoreWD): + """ + A rpc executer for the methods without arguments + """ + + name = "Minion Remote Link Executer" + + template =""" +
+ ${for_widget.display()} +
Minion Result
+
+ """ + + def __init__(self,*args,**kwargs): + """The init part here""" + super(SomeRemoteLink,self).__init__(*args,**kwargs) + self.for_widget = LinkRemoteFunction( + name = "catexecuter", + action = "/catlister", + data = dict(give_all="all"), + update = "items" + ) + + -- cgit From d4eb4fe05f5d3478d4de4cc5849b17975adf8e76 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 12:17:54 +0300 Subject: change for my minion --- test/unittest/test_client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/unittest/test_client.py b/test/unittest/test_client.py index c92224e..12a47bc 100644 --- a/test/unittest/test_client.py +++ b/test/unittest/test_client.py @@ -14,7 +14,8 @@ import socket class BaseTest: # assume we are talking to localhost # th = socket.gethostname() - th = socket.getfqdn() + m = "acervirtual.evlan.com" + th = socket.getfqdn(m) nforks=1 async=False -- cgit From c06d90260d9e6b2d0862ebe0a7f432329daefe94 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 16:49:28 +0300 Subject: i think we need to know which argument is in which order so added to validator part to add it returning data srtucure with method_arguments --- func/minion/func_arg.py | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/func/minion/func_arg.py b/func/minion/func_arg.py index 4a5ed7e..8ca460a 100644 --- a/func/minion/func_arg.py +++ b/func/minion/func_arg.py @@ -103,6 +103,28 @@ class ArgCompatibility(object): return True + def is_all_arguments_registered(self,cls,method_name,arguments): + """ + Method inspects the method arguments and checks if the user + has registered all the arguments succesfully and also adds a + 'order' keyword to method arguments to + """ + import inspect + from itertools import chain + #get the arguments from real object we have [args],*arg,**kwarg,[defaults] + tmp_arguments=inspect.getargspec(getattr(cls,method_name)) + check_args=[arg for arg in chain(tmp_arguments[0],tmp_arguments[1:3]) if arg and arg!='self'] + print "The arguments taken from the inspect are :",check_args + #the size may change of the hash so should a copy of it + copy_arguments = arguments.copy() + for compare_arg in copy_arguments.iterkeys(): + if not compare_arg in check_args: + raise ArgumentRegistrationError("The argument %s is not in the %s"%(compare_arg,method_name)) + else: + #should set its ordering thing + arguments[compare_arg]['order']=check_args.index(compare_arg) + + return True def validate_all(self): """ @@ -123,7 +145,6 @@ class ArgCompatibility(object): for method in self.__args_to_check.iterkeys(): #here we got args or description part #check if user did submit something not in the __method_options - for method_option in self.__args_to_check[method].iterkeys(): if method_option not in self.__method_options: raise IncompatibleTypesException("There is no option for method_name like %s,possible ones are : %s"%(method_option,str(self.__method_options))) @@ -131,13 +152,15 @@ class ArgCompatibility(object): if method_option == "args": for argument in self.__args_to_check[method][method_option].itervalues(): #print argument + #check if user registered all the args and add to them ordering option! self._is_basic_types_compatible(argument) self._is_type_options_compatible(argument) return True -###The Exception classes here +###The Exception classes here they will be raised during the validation part +###If a module passes all the tests it is ready tobe registered class IncompatibleTypesException(Exception): @@ -167,4 +190,16 @@ class UnregisteredMethodArgument(IncompatibleTypesException): pass +class NonExistingMethodRegistered(IncompatibleTypesException): + """ + Raised when module writer registers a method that doesnt + exist in his/her module class (probably by mistake) + """ + pass +class ArgumentRegistrationError(IncompatibleTypesException): + """ + When user forgets to register soem of the arguments in the list + or adds some argument that is not there + """ + pass -- cgit From f835390c4362d95e6d9084577e662332b82e2a20 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 16:50:08 +0300 Subject: validating if all arguments are registered --- func/minion/modules/func_module.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 724a27b..e66f410 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -96,12 +96,15 @@ class FuncModule(object): return {} #see if user tried to register an not implemented method :) - for method in tmp_arg_dict.keys(): + for method in tmp_arg_dict.iterkeys(): if not hasattr(self,method): raise NonExistingMethodRegistered("%s is not in %s "%(method,self.__class__.__name__)) #create argument validation instance self.arg_comp = ArgCompatibility(tmp_arg_dict) + #see if all registered arguments are there + for method in tmp_arg_dict.iterkeys(): + self.is_all_arguments_registered(self,method,tmp_arg_dict[method]['args']) #see if the options that were used are OK.. self.arg_comp.validate_all() -- cgit From 3cf6b38bfcfef04d6c537df79be2d8d90a5fc80b Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 16:50:54 +0300 Subject: adding tests for is_all_arguments_registered part --- test/unittest/test_func_arg.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/test/unittest/test_func_arg.py b/test/unittest/test_func_arg.py index 1b9102c..8f0c967 100644 --- a/test/unittest/test_func_arg.py +++ b/test/unittest/test_func_arg.py @@ -33,7 +33,14 @@ class TestArgCompatibility: self.ac = ArgCompatibility(self.dummy_empty_args()) result = self.ac.validate_all() assert result == True - + + def test_is_all_arguments_registered(self): + #create the dummy class + tc = FooClass() + arguments = tc.register_method() + assert self.ac.is_all_arguments_registered(tc,'foomethod',arguments['foomethod']['args'])==True + print arguments + def dummy_no_getter(self): return {} @@ -112,5 +119,25 @@ class TestArgCompatibility: } +class FooClass(object): + """ + Sample class for testing the is_all_arguments_registered + method functionality ... + """ + + def foomethod(self,arg1,arg5,arg4,*arg,**kw): + pass + def register_method(self): + return{ + 'foomethod':{ + 'args':{ + 'arg1':{}, + 'arg4':{}, + 'arg5':{}, + 'arg':{}, + 'kw':{}, + } + } + } -- cgit From 9419566c1968db33b1d9d50ba02921c5bbe98c16 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 18:25:53 +0300 Subject: export iptables method arguments --- func/minion/modules/iptables/port.py | 85 ++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/func/minion/modules/iptables/port.py b/func/minion/modules/iptables/port.py index 370123b..3d3902b 100644 --- a/func/minion/modules/iptables/port.py +++ b/func/minion/modules/iptables/port.py @@ -128,6 +128,91 @@ class Port(func_module.FuncModule): clear_all("-D OUTPUT -p %s --%sport %s -d %s -j REJECT" % (prot, dir, port, ip) ) return call_if_policy("OUTPUT", "DROP", "-I OUTPUT -p %s --%sport %s -d %s -j ACCEPT" % (prot, dir, port, ip) ) + def register_method_args(self): + """ + Export the methods and their definitons + """ + #they are all same so just declare here + port={ + 'type':'string', + 'optional':False, + + } + ip={ + 'type':'string', + 'optional':False, + 'default':'0.0.0.0' + } + prot={ + 'type':'string', + 'options':['tcp','udp','icmp','sctp'], + 'default':'tcp', + 'optional':False + } + dir={ + 'type':'string', + 'default':'dst', + 'options':['src','dst'], + 'optional':False + } + + return { + 'drop_from':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + } + }, + 'reject_from':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + + } + }, + 'accept_from':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + + } + }, + 'drop_to':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + + } + }, + 'reject_to':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + + } + }, + 'accept_to':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + + } + }, + + } + def parse_dir(dir): if (dir == "dst"): return "d" -- cgit From 3bbc0f1d9a588ea0416dce9acb07de77efab51c0 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 19:05:09 +0300 Subject: fixing a silly mistake --- func/minion/modules/func_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index e66f410..53fd66b 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -104,7 +104,7 @@ class FuncModule(object): self.arg_comp = ArgCompatibility(tmp_arg_dict) #see if all registered arguments are there for method in tmp_arg_dict.iterkeys(): - self.is_all_arguments_registered(self,method,tmp_arg_dict[method]['args']) + self.arg_comp.is_all_arguments_registered(self,method,tmp_arg_dict[method]['args']) #see if the options that were used are OK.. self.arg_comp.validate_all() -- cgit From a041a0d7eb7848825512ce8a6ae8243710356dfb Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 19:15:59 +0300 Subject: forgot to add order keyword to basic allowed types so couldnt pass the tests :) --- func/minion/func_arg.py | 3 ++- test/unittest/test_func_arg.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/func/minion/func_arg.py b/func/minion/func_arg.py index 8ca460a..bf07f1e 100644 --- a/func/minion/func_arg.py +++ b/func/minion/func_arg.py @@ -32,7 +32,8 @@ class ArgCompatibility(object): 'max_length':0, 'validator':'', 'type':'', - 'default':None #its type is unknown + 'default':None, #its type is unknown, + 'order':0 } def __init__(self,get_args_result): diff --git a/test/unittest/test_func_arg.py b/test/unittest/test_func_arg.py index 8f0c967..92a4b41 100644 --- a/test/unittest/test_func_arg.py +++ b/test/unittest/test_func_arg.py @@ -40,6 +40,7 @@ class TestArgCompatibility: arguments = tc.register_method() assert self.ac.is_all_arguments_registered(tc,'foomethod',arguments['foomethod']['args'])==True print arguments + assert self.ac.validate_all()==True def dummy_no_getter(self): return {} -- cgit From 207dea025323340aeb72c61cf499f348828f393f Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 19:28:28 +0300 Subject: haah i can not pass my unittests --- func/minion/func_arg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/func/minion/func_arg.py b/func/minion/func_arg.py index bf07f1e..bde5388 100644 --- a/func/minion/func_arg.py +++ b/func/minion/func_arg.py @@ -17,7 +17,7 @@ class ArgCompatibility(object): """ #these are the common options can be used with all types - __common_options = ('optional','default','description') + __common_options = ('optional','default','description','order') __method_options = ('description','args') #making method declarations more generic like method_name:{'args':{...},'description':"bla bla"} #basic types has types also -- cgit From b5c8fc4523039556152c5e49fe01a122103487d0 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 19:54:34 +0300 Subject: ah i forgot about that weird python behaviour :) --- funcweb/funcweb/controllers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/funcweb/funcweb/controllers.py b/funcweb/funcweb/controllers.py index 8dba678..d53d01d 100644 --- a/funcweb/funcweb/controllers.py +++ b/funcweb/funcweb/controllers.py @@ -51,7 +51,7 @@ class Root(controllers.RootController): @expose(template="funcweb.templates.method_args") #@identity.require(identity.not_anonymous()) - def method_display(self,minion="*",module="service",method="reload"): + def method_display(self,minion=None,module=None,method=None): fc = Overlord(minion) method_args = getattr(fc,module).get_method_args() -- cgit From a48f1c7a7a9dc1d0563f852b0fc9d506044a00fe Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 21:18:29 +0300 Subject: remove the weird duplication in widget.display --- funcweb/funcweb/controllers.py | 15 ++++++++------- funcweb/funcweb/widget_automation.py | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/funcweb/funcweb/controllers.py b/funcweb/funcweb/controllers.py index d53d01d..adf52b2 100644 --- a/funcweb/funcweb/controllers.py +++ b/funcweb/funcweb/controllers.py @@ -4,6 +4,7 @@ log = logging.getLogger(__name__) from turbogears import controllers, expose, flash, identity, redirect from func.overlord.client import Overlord, Minions from turbogears import mochikit +from funcweb.widget_automation import WidgetListFactory,RemoteFormAutomation,RemoteFormFactory class Root(controllers.RootController): @@ -52,7 +53,7 @@ class Root(controllers.RootController): @expose(template="funcweb.templates.method_args") #@identity.require(identity.not_anonymous()) def method_display(self,minion=None,module=None,method=None): - + fc = Overlord(minion) method_args = getattr(fc,module).get_method_args() @@ -60,15 +61,15 @@ class Root(controllers.RootController): print "Not registered method here" return dict(minion_form = None) - print method the_one = method_args[minion][method]['args'] if the_one: - - from funcweb.widget_automation import WidgetListFactory,RemoteFormAutomation,RemoteFormFactory wlist_object = WidgetListFactory(the_one) - wlist_object=wlist_object.get_widgetlist_object() - minion_form =RemoteFormFactory(wlist_object).get_remote_form() - #minion_form = RemoteFormAutomation(wlist_object) + wlist_object = wlist_object.get_widgetlist_object() + #minion_form =RemoteFormFactory( wlist_object.get_widgetlist_object()).get_remote_form() + minion_form = RemoteFormAutomation(wlist_object) + + del wlist_object + del the_one #print minion_form.fields #print minion_form diff --git a/funcweb/funcweb/widget_automation.py b/funcweb/funcweb/widget_automation.py index e27d865..68b4108 100644 --- a/funcweb/funcweb/widget_automation.py +++ b/funcweb/funcweb/widget_automation.py @@ -31,7 +31,6 @@ class WidgetListFactory(object): 'default_value':"TextArea"} } #will contain the input widget created in that class - __widget_list={} def __init__(self,argument_dict): """ @@ -43,7 +42,8 @@ class WidgetListFactory(object): """ self.__argument_dict = argument_dict - + self.__widget_list={} + def __add_general_widget(self): #key is the argument_name and the argument are options -- cgit From f1dedb34e548f3a9249835ba09dab1192eb16946 Mon Sep 17 00:00:00 2001 From: makkalot Date: Sun, 15 Jun 2008 21:51:40 +0300 Subject: show only the stuff that has exported methods,hmm it is slow --- funcweb/funcweb/controllers.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/funcweb/funcweb/controllers.py b/funcweb/funcweb/controllers.py index adf52b2..51dd20d 100644 --- a/funcweb/funcweb/controllers.py +++ b/funcweb/funcweb/controllers.py @@ -30,6 +30,15 @@ class Root(controllers.RootController): if not module: # list all modules #just list those who have get_method_args modules = fc.system.list_modules() + display_modules = [] + #FIXME slow really i know ! + for module in modules.itervalues(): + for mod in module: + if getattr(fc,mod).get_method_args()[name]: + display_modules.append(mod) + modules = {} + modules[name]=display_modules + return dict(modules=modules) else: # a module is specified if method: # minion.module.method specified; bring up execution form -- cgit From 4b367a5d5759c7c2b2307ffb195172d8b87f5e74 Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 16 Jun 2008 00:50:32 +0300 Subject: adding the minion,module,method as hidden fields --- funcweb/funcweb/widget_automation.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/funcweb/funcweb/widget_automation.py b/funcweb/funcweb/widget_automation.py index 68b4108..412da34 100644 --- a/funcweb/funcweb/widget_automation.py +++ b/funcweb/funcweb/widget_automation.py @@ -32,7 +32,7 @@ class WidgetListFactory(object): } #will contain the input widget created in that class - def __init__(self,argument_dict): + def __init__(self,argument_dict,minion=None,module=None,method=None): """ Initiated with argument_dict of a method to return back a WidgetsList object to be placed into a form object @@ -43,6 +43,11 @@ class WidgetListFactory(object): self.__argument_dict = argument_dict self.__widget_list={} + + #these fields will be passed ass hidden so we need them + self.minion = minion + self.module = module + self.method = method def __add_general_widget(self): @@ -76,6 +81,16 @@ class WidgetListFactory(object): #print "That have the object :",getattr(self.__widget_list["list_default"],"default") + #adding the hidden fields (that part wass adde later can be made more generic) + if self.minion: + self.__widget_list['minion']= getattr(widgets,'HiddenField')(name="minion",value=self.minion,default=self.minion) + if self.module: + self.__widget_list['module']= getattr(widgets,'HiddenField')(name="module",value=self.module,default=self.module) + if self.method: + self.__widget_list['method']= getattr(widgets,'HiddenField')(name="method",value=self.method,default=self.method) + + + def __add_specialized_string(self,argument,argument_name): """ Specialized option adder, called when the type:string is used -- cgit From 5cfa0d9d920a84f3b72bee8baf2afdada6dcd38b Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 16 Jun 2008 00:51:42 +0300 Subject: to be able to execute forms :) --- funcweb/funcweb/controllers.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/funcweb/funcweb/controllers.py b/funcweb/funcweb/controllers.py index 51dd20d..f3ffead 100644 --- a/funcweb/funcweb/controllers.py +++ b/funcweb/funcweb/controllers.py @@ -72,9 +72,10 @@ class Root(controllers.RootController): the_one = method_args[minion][method]['args'] if the_one: - wlist_object = WidgetListFactory(the_one) + wlist_object = WidgetListFactory(the_one,minion=minion,module=module,method=method) wlist_object = wlist_object.get_widgetlist_object() #minion_form =RemoteFormFactory( wlist_object.get_widgetlist_object()).get_remote_form() + minion_form = RemoteFormAutomation(wlist_object) del wlist_object @@ -118,7 +119,35 @@ class Root(controllers.RootController): """ Data processing part """ - return "I got that data from the remote minion form :
%r"%kw + if kw.has_key('minion') and kw.has_key('module') and kw.has_key('method'): + #do the stuff here + #assign them because we need the rest so dont control everytime + #and dont make lookup everytime ... + minion = kw['minion'] + del kw['minion'] + module = kw['module'] + del kw['module'] + method = kw['method'] + del kw['method'] + + #everytime we do that should be a clever way for that ??? + fc = Overlord(minion) + #get again the method args to get their order : + arguments=getattr(fc,module).get_method_args() + #so we know the order just allocate and put them there + cmd_args=['']*(len(kw.keys())) + + for arg in kw.keys(): + #wow what a lookup :) + index_of_arg = arguments[minion][method]['args'][arg]['order'] + cmd_args[index_of_arg]=kw[arg] + + #now execute the stuff + result = getattr(getattr(fc,module),method)(*cmd_args) + return "The list to be executed is \n: %s"%str(result) + + else: + return "Missing arguments sorry can not proceess the form" @expose() -- cgit From 012e36e7b35c275af40193bd149e6acdc6a6046d Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 16 Jun 2008 00:52:16 +0300 Subject: update the tests for new hiddenfield stuff --- funcweb/funcweb/tests/test_widget_automation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/funcweb/funcweb/tests/test_widget_automation.py b/funcweb/funcweb/tests/test_widget_automation.py index a81bc1e..3bc81e4 100644 --- a/funcweb/funcweb/tests/test_widget_automation.py +++ b/funcweb/funcweb/tests/test_widget_automation.py @@ -11,7 +11,7 @@ cherrypy.root = Root() class TestWidgetListFactory(unittest.TestCase): def setUp(self): - self.widget_factory = WidgetListFactory(self.get_test_default_args()) + self.widget_factory = WidgetListFactory(self.get_test_default_args(),minion="myminion",module="mymodule",method="my_method") def tearDown(self): -- cgit From 8912b953e675a2922b9497dd7adca3e6d364f2b2 Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 16 Jun 2008 12:18:08 +0300 Subject: adding implementation for methods without arguments for those that birngup some info --- funcweb/funcweb/controllers.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/funcweb/funcweb/controllers.py b/funcweb/funcweb/controllers.py index f3ffead..b2a2ca9 100644 --- a/funcweb/funcweb/controllers.py +++ b/funcweb/funcweb/controllers.py @@ -34,6 +34,7 @@ class Root(controllers.RootController): #FIXME slow really i know ! for module in modules.itervalues(): for mod in module: + #if it is not empty if getattr(fc,mod).get_method_args()[name]: display_modules.append(mod) modules = {} @@ -50,15 +51,6 @@ class Root(controllers.RootController): tg_template="funcweb.templates.module") - @expose(template="funcweb.templates.run") - #@identity.require(identity.not_anonymous()) - def run(self, minion="*", module=None, method=None, arguments=''): - fc = Overlord(minion) - results = getattr(getattr(fc, module), method)(*arguments.split()) - cmd = "%s.%s.%s(%s)" % (minion, module, method, arguments) - return dict(cmd=cmd, results=results) - - @expose(template="funcweb.templates.method_args") #@identity.require(identity.not_anonymous()) def method_display(self,minion=None,module=None,method=None): @@ -68,7 +60,7 @@ class Root(controllers.RootController): if not method_args.values(): print "Not registered method here" - return dict(minion_form = None) + return dict(minion_form = None,minion=minion,module=module,method=method) the_one = method_args[minion][method]['args'] if the_one: @@ -83,9 +75,9 @@ class Root(controllers.RootController): #print minion_form.fields #print minion_form - return dict(minion_form=minion_form) + return dict(minion_form =minion_form,minion=minion,module=module,method=method) else: - return dict(minion_form = None) + return dict(minion_form = None,minion=minion,module=module,method=method) @expose(template="funcweb.templates.login") @@ -149,6 +141,18 @@ class Root(controllers.RootController): else: return "Missing arguments sorry can not proceess the form" + @expose(template="funcweb.templates.method_args") + def execute_link(self,minion=None,module=None,method=None): + """ + Method is fot those minion methods that dont accept any + arguments so they provide only some information,executed + by pressing only the link ! + """ + fc = Overlord(minion) + result = getattr(getattr(fc,module),method)() + return str(result) + + @expose() def logout(self): -- cgit From 05341feebfa9d1f8dbf531fb1c1249edf910d960 Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 16 Jun 2008 12:19:12 +0300 Subject: add the magic jquery part for the method_args template for link execution --- funcweb/funcweb/templates/method_args.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/funcweb/funcweb/templates/method_args.html b/funcweb/funcweb/templates/method_args.html index 42946a8..2e7d4bd 100644 --- a/funcweb/funcweb/templates/method_args.html +++ b/funcweb/funcweb/templates/method_args.html @@ -7,6 +7,10 @@
${ET(minion_form.display(displays_on='genshi'))}
+
+ Run Method +
+
-- cgit From f58d369ffd61587c8af3c65d30812e4209bfe3df Mon Sep 17 00:00:00 2001 From: makkalot Date: Mon, 16 Jun 2008 21:36:55 +0300 Subject: change test for localhost --- test/unittest/test_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unittest/test_client.py b/test/unittest/test_client.py index 12a47bc..f3b441d 100644 --- a/test/unittest/test_client.py +++ b/test/unittest/test_client.py @@ -14,8 +14,7 @@ import socket class BaseTest: # assume we are talking to localhost # th = socket.gethostname() - m = "acervirtual.evlan.com" - th = socket.getfqdn(m) + th = socket.getfqdn() nforks=1 async=False @@ -50,6 +49,7 @@ class BaseTest: def test_module_get_method_args(self): mod = getattr(self.overlord,self.module) arg_result=mod.get_method_args() + print arg_result self.assert_on_fault(arg_result) def test_module_inventory(self): -- cgit From eaf715c340bf9a3cd032e607e21905426380b45f Mon Sep 17 00:00:00 2001 From: makkalot Date: Wed, 18 Jun 2008 13:57:23 +0300 Subject: adding resources for remote form that file fixes the ajaxian problem we had --- funcweb/funcweb/static/javascript/ajax.js | 83 +++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 funcweb/funcweb/static/javascript/ajax.js diff --git a/funcweb/funcweb/static/javascript/ajax.js b/funcweb/funcweb/static/javascript/ajax.js new file mode 100644 index 0000000..7df4749 --- /dev/null +++ b/funcweb/funcweb/static/javascript/ajax.js @@ -0,0 +1,83 @@ +function remoteFormRequest(form, target, options) { + var query = Array(); + var contents = formContents(form); + for (var j=0; j Date: Wed, 18 Jun 2008 13:58:06 +0300 Subject: adding the js file into master --- funcweb/funcweb/templates/master.html | 1 + 1 file changed, 1 insertion(+) diff --git a/funcweb/funcweb/templates/master.html b/funcweb/funcweb/templates/master.html index 33d14f9..073adc1 100644 --- a/funcweb/funcweb/templates/master.html +++ b/funcweb/funcweb/templates/master.html @@ -11,6 +11,7 @@