* luci/libs/uvl:
authorJo-Philipp Wich <jow@openwrt.org>
Tue, 2 Sep 2008 22:13:52 +0000 (22:13 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Tue, 2 Sep 2008 22:13:52 +0000 (22:13 +0000)
- fix handling of missing package/section/variable fields in scheme specs
- fix dereferencing of scheme tables in luci.uvl.uvlitem.scheme()
- unify TYPE_VARIABLE and TYPE_OPTION
- implement external "regexp:..." validators
- extend reference scheme to implement "lazylist" type for lists

libs/uvl/luasrc/uvl.lua
libs/uvl/luasrc/uvl/validation.lua
libs/uvl/root/lib/uci/schema/meta/schema

index 7fb11b1..e5a6c75 100644 (file)
@@ -33,9 +33,8 @@ require("luci.uvl.dependencies")
 TYPE_SCHEME   = 0x00
 TYPE_CONFIG   = 0x01
 TYPE_SECTION  = 0x02
-TYPE_VARIABLE = 0x03
-TYPE_OPTION   = 0x04
-TYPE_ENUM     = 0x05
+TYPE_OPTION   = 0x03
+TYPE_ENUM     = 0x04
 
 --- Boolean; default true;
 -- treat sections found in config but not in scheme as error
@@ -306,7 +305,9 @@ function UVL._validate_option( self, option, nodeps )
                                if type(val) ~= "table" and STRICT_LIST_TYPE then
                                        return false, option:error(ERR.OPT_NOTLIST(option))
                                end
-                       elseif option:scheme('datatype') then
+                       end
+
+                       if option:scheme('datatype') then
                                local dt = option:scheme('datatype')
 
                                if self.datatypes[dt] then
@@ -378,10 +379,20 @@ end
 function UVL._read_scheme_parts( self, scheme, schemes )
 
        -- helper function to check for required fields
-       local function _req( c, t, r )
+       local function _req( t, n, c, r )
                for i, v in ipairs(r) do
-                       if not t[v] then
-                               return false, ERR.SME_REQFLD({c,t}, v)
+                       if not c[v] then
+                               local p, o = scheme:sid(), nil
+
+                               if t == TYPE_SECTION then
+                                       o = section( scheme, nil, p, n )
+                               elseif t == TYPE_OPTION then
+                                       o = option( scheme, nil, p, '(nil)', n )
+                               elseif t == TYPE_ENUM then
+                                       o = enum( scheme, nil, p, '(nil)', '(nil)', n )
+                               end
+
+                               return false, ERR.SME_REQFLD(o,v)
                        end
                end
                return true
@@ -393,7 +404,7 @@ function UVL._read_scheme_parts( self, scheme, schemes )
                if c == TYPE_SECTION then
                        k = "package"
                        n = 1
-               elseif c == TYPE_VARIABLE then
+               elseif c == TYPE_OPTION then
                        k = "section"
                        n = 2
                elseif c == TYPE_ENUM then
@@ -444,7 +455,7 @@ function UVL._read_scheme_parts( self, scheme, schemes )
                for k, v in pairs( conf ) do
                        if v['.type'] == 'section' then
 
-                               ok, err = _req( TYPE_SECTION, v, { "name", "package" } )
+                               ok, err = _req( TYPE_SECTION, k, v, { "name", "package" } )
                                if err then return false, scheme:error(err) end
 
                                local r, err = _ref( TYPE_SECTION, v )
@@ -496,10 +507,10 @@ function UVL._read_scheme_parts( self, scheme, schemes )
                for k, v in pairs( conf ) do
                        if v['.type'] == "variable" then
 
-                               ok, err = _req( TYPE_VARIABLE, v, { "name", "section" } )
+                               ok, err = _req( TYPE_OPTION, k, v, { "name", "section" } )
                                if err then return false, scheme:error(err) end
 
-                               local r, err = _ref( TYPE_VARIABLE, v )
+                               local r, err = _ref( TYPE_OPTION, v )
                                if err then return false, scheme:error(err) end
 
                                local p = self.packages[r[1]]
@@ -567,7 +578,7 @@ function UVL._read_scheme_parts( self, scheme, schemes )
                for k, v in pairs( conf ) do
                        if v['.type'] == "enum" then
 
-                               ok, err = _req( TYPE_ENUM, v, { "value", "variable" } )
+                               ok, err = _req( TYPE_ENUM, k, v, { "value", "variable" } )
                                if err then return false, scheme:error(err) end
 
                                local r, err = _ref( TYPE_ENUM, v )
@@ -682,6 +693,25 @@ function UVL._read_validator( self, values, validators )
                                validator = value:gsub("^exec:","")
                        elseif value:match("^lua:") then
                                validator = self:_resolve_function( (value:gsub("^lua:","") ) )
+                       elseif value:match("^regexp:") then
+                               local pattern = value:gsub("^regexp:","")
+                               validator = function( type, dtype, pack, sect, optn, ... )
+                                       local values = { ... }
+                                       for _, v in ipairs(values) do
+                                               local ok, match =
+                                                       luci.util.copcall( string.match, v, pattern )
+
+                                               if not ok then
+                                                       return false, match
+                                               elseif not match then
+                                                       return false,
+                                                               'Value "%s" does not match pattern "%s"' % {
+                                                                       v, pattern
+                                                               }
+                                               end
+                                       end
+                                       return true
+                               end
                        end
 
                        if validator then
@@ -774,16 +804,19 @@ function uvlitem.scheme(self, opt)
        local s
 
        if #self.sref == 4 or #self.sref == 3 then
-               s = self.s
-                       .packages[self.sref[1]]
-                       .variables[self.sref[2]][self.sref[3]]
+               s = self.s and self.s.packages
+               s = s      and s[self.sref[1]]
+               s = s      and s.variables
+               s = s      and s[self.sref[2]]
+               s = s      and s[self.sref[3]]
        elseif #self.sref == 2 then
-               s = self.s
-                       .packages[self.sref[1]]
-                       .sections[self.sref[2]]
+               s = self.s and self.s.packages
+               s = s      and s[self.sref[1]]
+               s = s      and s.sections
+               s = s      and s[self.sref[2]]
        else
-               s = self.s
-                       .packages[self.sref[1]]
+               s = self.s and self.s.packages
+               s = s      and s[self.sref[1]]
        end
 
        if s and opt then
index 0c6523f..50f9da0 100644 (file)
@@ -43,10 +43,14 @@ function check( self, object )
        if object:scheme('validators') then
                for _, val in ipairs(object:scheme('validators')) do
                        local ok, err = false, nil
+
+                       local values = object:value()
+                             values = type(values) == "table" and values or { values }
+
                        local args = {
-                               object:scheme('type'),
-                               object.cref[1], object.cref[2], object.cref[3],
-                               object:scheme('datatype'), object:value()
+                               object:scheme('type'), object:scheme('datatype'),
+                               object.cref[1], object.cref[2], object.cref[3] or '',
+                               unpack(values)
                        }
 
                        if type(val) == "function" then
index 2454a18..d424ef9 100644 (file)
@@ -38,7 +38,7 @@ config variable
        option name             'description'
        option title    'Description of the defined package'
        option section  'schema.package'
-       option type             'variable'
+       option type             'lazylist'
        option datatype 'string'
        option required false
 
@@ -92,7 +92,7 @@ config variable
        option name             'description'
        option title    'Description of the defined section'
        option section  'schema.section'
-       option type             'variable'
+       option type             'lazylist'
        option datatype 'string'
        option required false
 
@@ -101,7 +101,7 @@ config variable
        option name             'depends'
        option title    'List of dependencies within and between defined sections'
        option section  'schema.section'
-       option type             'list'
+       option type             'lazylist'
        option datatype 'string'
        option required false
 
@@ -191,7 +191,7 @@ config variable
        option name             'description'
        option title    'Description of the defined variable'
        option section  'schema.variable'
-       option type             'variable'
+       option type             'lazylist'
        option datatype 'string'
        option required false
 
@@ -200,7 +200,7 @@ config variable
        option name             'depends'
        option title    'List of dependencies between defined variables'
        option section  'schema.variable'
-       option type             'list'
+       option type             'lazylist'
        option datatype 'string'
        option required false
 
@@ -240,6 +240,12 @@ config enum
        option title    'This is a list variable'
        option variable 'schema.variable.type'
 
+# List-or-Option variable type (schema.@variable.type=lazylist)
+config enum
+       option value    'lazylist'
+       option title    'This is a list or option variable'
+       option variable 'schema.variable.type'
+
 # Reference variable type (schema.@variable.type=reference)
 config enum
        option value    'reference'
@@ -260,7 +266,7 @@ config variable
        option name             'validator'
        option title    'Datatype of this variable'
        option section  'schema.variable'
-       option type             'list'
+       option type             'lazylist'
        option datatype 'string'
        option required false
 
@@ -269,7 +275,7 @@ config variable
        option name             'valueof'
        option title    'Reference to section or option to read values from'
        option section  'schema.variable'
-       option type             'list'
+       option type             'lazylist'
        option datatype 'string'
        option required false
 
@@ -323,7 +329,7 @@ config variable
        option name             'description'
        option title    'Description of the defined enum value'
        option section  'schema.enum'
-       option type             'variable'
+       option type             'lazylist'
        option datatype 'string'
        option required false
 
@@ -332,7 +338,7 @@ config variable
        option name             'depends'
        option title    'List of dependencies on defined variables'
        option section  'schema.enum'
-       option type             'list'
+       option type             'lazylist'
        option datatype 'string'
        option required false