From 896ea2d579f29eeb0e5a6923b305005ceec3810a Mon Sep 17 00:00:00 2001 From: Giulio De Donato Date: Mon, 25 Feb 2013 12:08:09 +0100 Subject: [PATCH 1/4] added tols specification, key group fixed. --- README.md | 8 ++ tests/example.tols | 53 ++++++++++++ tols.md | 203 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 264 insertions(+) create mode 100644 tests/example.tols create mode 100644 tols.md diff --git a/README.md b/README.md index 30de2a12..d49ac01d 100644 --- a/README.md +++ b/README.md @@ -215,6 +215,14 @@ type = "apple" apple = "yes" ``` +Validate a toml file +---------- + +A TOML file could be validated with anoter file called TOLS. + +For more specification see [tols.md](tols.md) + + Seriously? ---------- diff --git a/tests/example.tols b/tests/example.tols new file mode 100644 index 00000000..a62c30ea --- /dev/null +++ b/tests/example.tols @@ -0,0 +1,53 @@ +# This is a TOLS document. Boom. +# This is also a TOML document. Boooom. + +[title.scheme] +primitive = "String" +required = true + +[owner] + [owner.name.scheme] + primitive = "String" + required = true + + [owner.organization.scheme] + primitive = "String" + required = false + + [owner.dob.scheme] + primitive = "Datetime" + required = true + range.min = 1913-05-27T07:32:00Z + range.max = 2013-05-27T07:32:00Z + +[database] + [database.server.scheme] + primitive = "String" + required = true + + [database.ports.scheme] + primitive = "Array" + required = true + range.min = 0 + content.primitive = "Integer" + content.range.min = 1024 + content.range.max = 49151 + + [database.connection_max.scheme] + primitive = "Integer" + required = false + default = 5000 + + [database.enabled.scheme] + primitive = "Boolean" + default = false + +# the toml should have at least one server with ip +[servers.0.ip.scheme] +primitive = "String" +required = true + +# having the following line doesn't change anything. +#[clients] +# primitive = "Array" +# required = false \ No newline at end of file diff --git a/tols.md b/tols.md new file mode 100644 index 00000000..3c283916 --- /dev/null +++ b/tols.md @@ -0,0 +1,203 @@ +TOLS +==== + +Tom's Obvious Liuggio Scheme. + +By Tom Preston-Werner, Giulio De Donato. + +TOLS is like XSD, only more readable and simpler. + +There are 3 simple rules to follow: + +- A TOLS file is itself a valid TOML file. +- Each element could be validated. +- Explicit validation - if an element has not a validation scheme is valid by default. + +Use cases +---------- + +Given a TOLS file, as developer I want to **validate** an existant TOML file, having the proper **default** values. + +Given a TOLS file, as developer I want to easily **create** a TOML file. + +Example +------- + +```toml +# This is a TOLS document. Boom. +# This is also a TOML document. Boooom. (see rule n.1) + +[title.scheme] # scheme is a keyword +primitive = "String" # the title must be a String +required = true # +length.max = 254 # max string length (exclusive <) + +[age.scheme] +primitive = "Integer" # the age must be an Integer +range.max = 100 # age is not required, but if the value is defined, should be maximum 100 (exclusive <) +range.min = 17 # age is not required, but if the value is defined, should be minimum 17 (exclusive >) +``` + +The above validates the following two examples + +```toml +title = "TOML Example" +age = 34 +``` + +```toml +title = "TOML Example" +``` + +and also could help to **generate** a toml file (see use case n.2) + +```toml +title = "" +# age = 18 +``` + +# Boolean example + +```toml +# toml +enabled = true +``` + +```toml +# tols +[enabled.scheme] +primitive = "Boolean" # Typing the enable value to Boolean +default = true +# required = false # if omitted the required is false by default +``` + +# Integer, Float and Datetime example < Boolean + +Integer, Float and Datetime share the same schema + +```toml +# toml +age = 34 +``` + +```toml +# tols +[age.scheme] +primitive = "Integer" # Typing the value +default = 190 # The default value for the current key +required = false # by default is false +range.min = 0 # (exclusive <) +range.max = 0 # (exclusive >) +``` + +# String example < Boolean + +```toml +# tols + +[email.scheme] +primitive = "String" # typing +required = true # default is false +# default = "liuggio@gmail.com" # the default value for the current key +length.max = 254 # max string length (exclusive <) +length.min = 5 # min length (exclusive >) +pattern= "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$" #regular expression +``` + +# Array + +```toml +# toml file +data = [ ["gamma", "delta"], [1, 2] ] +``` + +Here the scheme + +```toml +# tols + +[data.scheme] +primitive = "Array" # Typing +length.max = 2 # max array length (exclusive <) +length.min = 0 # min array length (exclusive >) +content.primitive = "Array" # in toml you can't mix data types, so you could explicit the first nested content +``` +Mmmm this is so easy, I want to validate also "gamma" and "delta" how could I do? + +```toml +# tols +[data] + [data.0.scheme] # this is the first element of data ["gamma", "delta"] + primitive = "Array" # is an Array + length.max = 2 # max length (exclusive <) + length.min = 0 # min length (exclusive >) + content.primitive = "String" # the content should be a String + content.length.max = 254 # content takes the String as scheme behaviour +# content.pattern = /?/ # regular expr + + [data.1.scheme] # we are validating the [1, 2] + primitive = "Array" # should be an array + length.max = 2 # max string length (exclusive <) + length.min = 0 # min length (exclusive >) + content.primitive = "Integer"# content takes the Integer Scheme Behaviour + content.range.min = 0 + content.range.max = 10 +``` + +# Hash + +```toml +# toml + +[fruit.type] +apple = "yes" +orange = "no" +``` + +```toml +# tols +[fruit.type.apple.scheme] +primitive = "String" +required = true +length.max = 3 +``` + +or just put the validation in the apple.type content + +```toml +# tols +[fruit.type.scheme] +primitive = "Hash" +required = true +length.max = 3 +content.primitive = "String" +content.required = true +content.length.max = 3 +``` + +All the keywords +------- + +TOLS schema has 8 keywords. + +- **schema** is an Hash and describes the behaviour for a defined field. + +- **primitive** could be: ["String", "Integer", "Float", "Boolean", "Datetime", "Array", "Hash"]. + +- **default** contains the default value for the current field. + +- **required** is a Boolean value, by default is false. + +- **length** is a hash that contains two values **min** and **max**, only when primitives are [String, Array, Hash]. + +- **range** is a hash that contains two values **min** and **max**, only when primitives are [Integer, Float, Datetime]. + +- **pattern** is a String and contains a valid Regular Expression only when primitives is a String. + +- **content** is a Hash and describes the behaviour of the first nested element. + + +TOLS is a valid TOML file, could I validate a TOLS file? +------- + +Don't drink too much man. From e1dd63d8831a711c13761fe64a181c6bae031478 Mon Sep 17 00:00:00 2001 From: Giulio De Donato Date: Tue, 26 Feb 2013 14:48:15 +0100 Subject: [PATCH 2/4] removed scheme --- tests/cache/cache.xml | 12 ++++++++++++ tests/example.tols | 36 +++++++++++++++++++++--------------- tols.md | 26 ++++++++++++-------------- 3 files changed, 45 insertions(+), 29 deletions(-) create mode 100644 tests/cache/cache.xml diff --git a/tests/cache/cache.xml b/tests/cache/cache.xml new file mode 100644 index 00000000..a95d3652 --- /dev/null +++ b/tests/cache/cache.xml @@ -0,0 +1,12 @@ + + + + 127.0.0.1 + + + + 127.0.0.2 + 127.0.0.3 + + + \ No newline at end of file diff --git a/tests/example.tols b/tests/example.tols index a62c30ea..a91b67bf 100644 --- a/tests/example.tols +++ b/tests/example.tols @@ -1,49 +1,55 @@ # This is a TOLS document. Boom. # This is also a TOML document. Boooom. -[title.scheme] +[title] primitive = "String" required = true [owner] - [owner.name.scheme] + [owner.name] primitive = "String" required = true - [owner.organization.scheme] + [owner.organization] primitive = "String" required = false - [owner.dob.scheme] + [owner.dob] primitive = "Datetime" required = true - range.min = 1913-05-27T07:32:00Z - range.max = 2013-05-27T07:32:00Z + [owner.dob.range] + min = 1913-05-27T07:32:00Z + max = 2013-05-27T07:32:00Z [database] - [database.server.scheme] + [database.server] primitive = "String" required = true - [database.ports.scheme] + [database.ports] primitive = "Array" required = true - range.min = 0 - content.primitive = "Integer" - content.range.min = 1024 - content.range.max = 49151 + [database.ports.range] + min = 0 - [database.connection_max.scheme] + [database.ports.content] + primitive = "Integer" + + [database.ports.content.range] + min = 1024 + max = 49151 + + [database.connection_max] primitive = "Integer" required = false default = 5000 - [database.enabled.scheme] + [database.enabled] primitive = "Boolean" default = false # the toml should have at least one server with ip -[servers.0.ip.scheme] +[servers.0.ip] primitive = "String" required = true diff --git a/tols.md b/tols.md index 3c283916..1a620f56 100644 --- a/tols.md +++ b/tols.md @@ -27,12 +27,12 @@ Example # This is a TOLS document. Boom. # This is also a TOML document. Boooom. (see rule n.1) -[title.scheme] # scheme is a keyword +[title] primitive = "String" # the title must be a String required = true # length.max = 254 # max string length (exclusive <) -[age.scheme] +[age] primitive = "Integer" # the age must be an Integer range.max = 100 # age is not required, but if the value is defined, should be maximum 100 (exclusive <) range.min = 17 # age is not required, but if the value is defined, should be minimum 17 (exclusive >) @@ -65,7 +65,7 @@ enabled = true ```toml # tols -[enabled.scheme] +[enabled] primitive = "Boolean" # Typing the enable value to Boolean default = true # required = false # if omitted the required is false by default @@ -82,7 +82,7 @@ age = 34 ```toml # tols -[age.scheme] +[age] primitive = "Integer" # Typing the value default = 190 # The default value for the current key required = false # by default is false @@ -95,7 +95,7 @@ range.max = 0 # (exclusive >) ```toml # tols -[email.scheme] +[email] primitive = "String" # typing required = true # default is false # default = "liuggio@gmail.com" # the default value for the current key @@ -111,12 +111,12 @@ pattern= "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$" #regular expression data = [ ["gamma", "delta"], [1, 2] ] ``` -Here the scheme +Here the scheme validator ```toml # tols -[data.scheme] +[data] primitive = "Array" # Typing length.max = 2 # max array length (exclusive <) length.min = 0 # min array length (exclusive >) @@ -127,7 +127,7 @@ Mmmm this is so easy, I want to validate also "gamma" and "delta" how could I do ```toml # tols [data] - [data.0.scheme] # this is the first element of data ["gamma", "delta"] + [data.0] # this is the first element of data ["gamma", "delta"] primitive = "Array" # is an Array length.max = 2 # max length (exclusive <) length.min = 0 # min length (exclusive >) @@ -135,7 +135,7 @@ Mmmm this is so easy, I want to validate also "gamma" and "delta" how could I do content.length.max = 254 # content takes the String as scheme behaviour # content.pattern = /?/ # regular expr - [data.1.scheme] # we are validating the [1, 2] + [data.1] # we are validating the [1, 2] primitive = "Array" # should be an array length.max = 2 # max string length (exclusive <) length.min = 0 # min length (exclusive >) @@ -156,7 +156,7 @@ orange = "no" ```toml # tols -[fruit.type.apple.scheme] +[fruit.type.apple] primitive = "String" required = true length.max = 3 @@ -166,7 +166,7 @@ or just put the validation in the apple.type content ```toml # tols -[fruit.type.scheme] +[fruit.type] primitive = "Hash" required = true length.max = 3 @@ -178,9 +178,7 @@ content.length.max = 3 All the keywords ------- -TOLS schema has 8 keywords. - -- **schema** is an Hash and describes the behaviour for a defined field. +TOLS schema has 7 keywords. - **primitive** could be: ["String", "Integer", "Float", "Boolean", "Datetime", "Array", "Hash"]. From 9b0530d318255b4759edd6c773022272d2fe93ce Mon Sep 17 00:00:00 2001 From: Giulio De Donato Date: Tue, 26 Feb 2013 15:06:41 +0100 Subject: [PATCH 3/4] tols examples are now is a valid toml --- tests/cache/cache.xml | 12 -------- tols.md | 70 ++++++++++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 39 deletions(-) delete mode 100644 tests/cache/cache.xml diff --git a/tests/cache/cache.xml b/tests/cache/cache.xml deleted file mode 100644 index a95d3652..00000000 --- a/tests/cache/cache.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - 127.0.0.1 - - - - 127.0.0.2 - 127.0.0.3 - - - \ No newline at end of file diff --git a/tols.md b/tols.md index 1a620f56..3ba1edcc 100644 --- a/tols.md +++ b/tols.md @@ -30,15 +30,17 @@ Example [title] primitive = "String" # the title must be a String required = true # -length.max = 254 # max string length (exclusive <) + [title.length] + max = 254 # max string length (exclusive <) [age] primitive = "Integer" # the age must be an Integer -range.max = 100 # age is not required, but if the value is defined, should be maximum 100 (exclusive <) -range.min = 17 # age is not required, but if the value is defined, should be minimum 17 (exclusive >) + [age.range] + min = 17 # age is not required, but if the value is defined, should be minimum 17 (exclusive >) + max = 100 # age is not required, but if the value is defined, should be maximum 100 (exclusive <) ``` -The above validates the following two examples +The above **validates** the following two examples ```toml title = "TOML Example" @@ -49,7 +51,7 @@ age = 34 title = "TOML Example" ``` -and also could help to **generate** a toml file (see use case n.2) +and also could help to **generates** a toml file (see use case n.2) ```toml title = "" @@ -86,8 +88,9 @@ age = 34 primitive = "Integer" # Typing the value default = 190 # The default value for the current key required = false # by default is false -range.min = 0 # (exclusive <) -range.max = 0 # (exclusive >) + [age.range] + min = 0 # (exclusive <) + max = 0 # (exclusive >) ``` # String example < Boolean @@ -99,8 +102,9 @@ range.max = 0 # (exclusive >) primitive = "String" # typing required = true # default is false # default = "liuggio@gmail.com" # the default value for the current key -length.max = 254 # max string length (exclusive <) -length.min = 5 # min length (exclusive >) + [email.length] + max = 254 # max string length (exclusive <) + min = 5 # min length (exclusive >) pattern= "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$" #regular expression ``` @@ -118,9 +122,11 @@ Here the scheme validator [data] primitive = "Array" # Typing -length.max = 2 # max array length (exclusive <) -length.min = 0 # min array length (exclusive >) -content.primitive = "Array" # in toml you can't mix data types, so you could explicit the first nested content + [data.length] + max = 2 # max array length (exclusive <) + min = 0 # min array length (exclusive >) + [data.content] + primitive = "Array" # in toml you can't mix data types, so you could explicit the first nested content ``` Mmmm this is so easy, I want to validate also "gamma" and "delta" how could I do? @@ -129,19 +135,25 @@ Mmmm this is so easy, I want to validate also "gamma" and "delta" how could I do [data] [data.0] # this is the first element of data ["gamma", "delta"] primitive = "Array" # is an Array - length.max = 2 # max length (exclusive <) - length.min = 0 # min length (exclusive >) - content.primitive = "String" # the content should be a String - content.length.max = 254 # content takes the String as scheme behaviour -# content.pattern = /?/ # regular expr + [data.0.length] + max = 2 # max length (exclusive <) + min = 0 # min length (exclusive >) + [data.0.content] + primitive = "String" # the content should be a String +# pattern = /?/ # regular expr + [data.0.content.length] + max = 254 # content takes the String as scheme behaviour [data.1] # we are validating the [1, 2] primitive = "Array" # should be an array - length.max = 2 # max string length (exclusive <) - length.min = 0 # min length (exclusive >) - content.primitive = "Integer"# content takes the Integer Scheme Behaviour - content.range.min = 0 - content.range.max = 10 + [data.1.length] + max = 2 # max string length (exclusive <) + min = 0 # min length (exclusive >) + [data.0.content] + primitive = "Integer" # content takes the Integer Scheme Behaviour + [data.0.content.range] + min = 0 + max = 10 ``` # Hash @@ -159,7 +171,8 @@ orange = "no" [fruit.type.apple] primitive = "String" required = true -length.max = 3 + [fruit.type.apple.length] + max = 3 ``` or just put the validation in the apple.type content @@ -169,10 +182,13 @@ or just put the validation in the apple.type content [fruit.type] primitive = "Hash" required = true -length.max = 3 -content.primitive = "String" -content.required = true -content.length.max = 3 + [fruit.type.apple.length] + max = 3 + [fruit.type.apple.content] + primitive = "String" + required = true + [fruit.type.apple.content.length] + max = 3 ``` All the keywords From 18d27e923b91f4fd8d05207eb307f383e55dced3 Mon Sep 17 00:00:00 2001 From: Giulio De Donato Date: Tue, 26 Feb 2013 16:28:20 +0100 Subject: [PATCH 4/4] added occurrence, in and notin --- README.md | 2 +- tests/cache/cache-1.0.xsd | 38 ++++++++++++++++++++++++++++++++++++++ tests/cache/cache.tols | 36 ++++++++++++++++++++++++++++++++++++ tests/cache/cache.toml | 13 +++++++++++++ tests/cache/cache.xml | 12 ++++++++++++ tests/cache/cache.yml | 14 ++++++++++++++ tols.md | 8 ++++++-- 7 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 tests/cache/cache-1.0.xsd create mode 100644 tests/cache/cache.tols create mode 100644 tests/cache/cache.toml create mode 100644 tests/cache/cache.xml create mode 100644 tests/cache/cache.yml diff --git a/README.md b/README.md index d49ac01d..728424fe 100644 --- a/README.md +++ b/README.md @@ -218,7 +218,7 @@ apple = "yes" Validate a toml file ---------- -A TOML file could be validated with anoter file called TOLS. +A **TOML** file can be created and validated thanks to a **TOLS** file. For more specification see [tols.md](tols.md) diff --git a/tests/cache/cache-1.0.xsd b/tests/cache/cache-1.0.xsd new file mode 100644 index 00000000..05c89729 --- /dev/null +++ b/tests/cache/cache-1.0.xsd @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cache/cache.tols b/tests/cache/cache.tols new file mode 100644 index 00000000..534f8abb --- /dev/null +++ b/tests/cache/cache.tols @@ -0,0 +1,36 @@ +[cache.clients] +primitive = "Hash" # could be omitted + [cache.clients.client] # defines a new prototype, its name is not important + primitive = "Hash" + [cache.clients.client.occurrence] + min = 0 # at least one occurrence, no maximum +# start the prototype + [cache.clients.client.type] + primitive = "String" # typing + required = true # default is false + [cache.clients.client.type.range] + in = ["redis", "memcache"] + notin = ["mysql"] #mysql as cache is not supported + + [cache.clients.client.alias] + primitive = "String" # typing + required = true # default is false + + [cache.clients.client.dsn] + primitive = "Array" + [cache.clients.client.dsn.content] + primitive = "String" + pattern = "^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$" # regex for ip address, this is an example is not working + + [cache.clients.client.logging] + primitive = "Boolean" + default = true + + [cache.clients.client.options] + primitive = "Hash" + [cache.clients.client.options.connection_persistent] + primitive = "Boolean" + default = true + + [cache.clients.client.options.connection_timeout] + primitive = "Integer" \ No newline at end of file diff --git a/tests/cache/cache.toml b/tests/cache/cache.toml new file mode 100644 index 00000000..e283994c --- /dev/null +++ b/tests/cache/cache.toml @@ -0,0 +1,13 @@ +[cache.clients.default] +type = "redis" +alias = "default" +dsn = ["127.0.0.1"] +logging = false + +[cache.clients.secondary] +type = "memcache" +alias = "secondary" +dsn = ["127.0.0.2", "127.0.0.3"] +logging = false + [cache.clients.secondary.options] + connection_persistent = true \ No newline at end of file diff --git a/tests/cache/cache.xml b/tests/cache/cache.xml new file mode 100644 index 00000000..7036a94e --- /dev/null +++ b/tests/cache/cache.xml @@ -0,0 +1,12 @@ + + + + 127.0.0.1 + + + + 127.0.0.2 + 127.0.0.3 + + + \ No newline at end of file diff --git a/tests/cache/cache.yml b/tests/cache/cache.yml new file mode 100644 index 00000000..345740b6 --- /dev/null +++ b/tests/cache/cache.yml @@ -0,0 +1,14 @@ +cache: + clients: + default: + type: redis + alias: default + dsn: 127.0.0.1 + logging: true + secondary: + type: memcache + alias: secondary + dsn: [127.0.0.2, 127.0.0.3] + logging: false + options: + connection_persistent: true \ No newline at end of file diff --git a/tols.md b/tols.md index 3ba1edcc..0c5c519b 100644 --- a/tols.md +++ b/tols.md @@ -105,6 +105,8 @@ required = true # default is false [email.length] max = 254 # max string length (exclusive <) min = 5 # min length (exclusive >) + [email.range] + in = ["tom@github.com", "liuggio@gmail.com"] # email could be one of pattern= "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$" #regular expression ``` @@ -194,7 +196,7 @@ required = true All the keywords ------- -TOLS schema has 7 keywords. +TOLS schema has 12 keywords to know. - **primitive** could be: ["String", "Integer", "Float", "Boolean", "Datetime", "Array", "Hash"]. @@ -204,12 +206,14 @@ TOLS schema has 7 keywords. - **length** is a hash that contains two values **min** and **max**, only when primitives are [String, Array, Hash]. -- **range** is a hash that contains two values **min** and **max**, only when primitives are [Integer, Float, Datetime]. +- **range** is a hash that contains values **min** and **max**, only when primitives are [Integer, Float, Datetime], + and **in** and **notin** for all primitives. - **pattern** is a String and contains a valid Regular Expression only when primitives is a String. - **content** is a Hash and describes the behaviour of the first nested element. +- **occurrence** define the number of repetition of a primitive, is a hash with two values **min** and **max**. TOLS is a valid TOML file, could I validate a TOLS file? -------