* 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_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
 
 --- 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
                                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
                                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
 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
                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
                        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
                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
                        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
 
                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 )
                                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
 
                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
 
                                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]]
                                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
 
                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 )
                                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:","") ) )
                                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
                        end
 
                        if validator then
@@ -774,16 +804,19 @@ function uvlitem.scheme(self, opt)
        local s
 
        if #self.sref == 4 or #self.sref == 3 then
        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
        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
        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
        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
        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 = {
                        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
                        }
 
                        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 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
 
        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 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
 
        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 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
 
        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 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
 
        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 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
 
        option datatype 'string'
        option required false
 
@@ -240,6 +240,12 @@ config enum
        option title    'This is a list variable'
        option variable 'schema.variable.type'
 
        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'
 # 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 name             'validator'
        option title    'Datatype of this variable'
        option section  'schema.variable'
-       option type             'list'
+       option type             'lazylist'
        option datatype 'string'
        option required false
 
        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 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
 
        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 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
 
        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 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
 
        option datatype 'string'
        option required false