tableschema 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +21 -0
- data/.travis.yml +15 -1
- data/README.md +164 -129
- data/Rakefile +10 -1
- data/bin/console +2 -6
- data/{etc/schemas → lib/profiles}/geojson.json +0 -1
- data/lib/profiles/table-schema.json +1625 -0
- data/lib/profiles/topojson.json +311 -0
- data/lib/tableschema.rb +5 -3
- data/lib/tableschema/constraints/constraints.rb +12 -24
- data/lib/tableschema/constraints/enum.rb +6 -2
- data/lib/tableschema/constraints/max_length.rb +6 -2
- data/lib/tableschema/constraints/maximum.rb +12 -2
- data/lib/tableschema/constraints/min_length.rb +6 -2
- data/lib/tableschema/constraints/minimum.rb +12 -2
- data/lib/tableschema/constraints/pattern.rb +9 -2
- data/lib/tableschema/constraints/required.rb +6 -15
- data/lib/tableschema/constraints/unique.rb +12 -0
- data/lib/tableschema/defaults.rb +9 -0
- data/lib/tableschema/exceptions.rb +15 -2
- data/lib/tableschema/field.rb +39 -20
- data/lib/tableschema/helpers.rb +32 -15
- data/lib/tableschema/infer.rb +31 -28
- data/lib/tableschema/model.rb +57 -34
- data/lib/tableschema/schema.rb +40 -6
- data/lib/tableschema/table.rb +75 -26
- data/lib/tableschema/types/any.rb +1 -0
- data/lib/tableschema/types/array.rb +2 -1
- data/lib/tableschema/types/base.rb +9 -21
- data/lib/tableschema/types/date.rb +1 -0
- data/lib/tableschema/types/datetime.rb +1 -0
- data/lib/tableschema/types/duration.rb +31 -0
- data/lib/tableschema/types/geojson.rb +27 -5
- data/lib/tableschema/types/geopoint.rb +4 -3
- data/lib/tableschema/types/integer.rb +1 -0
- data/lib/tableschema/types/number.rb +40 -25
- data/lib/tableschema/types/object.rb +2 -1
- data/lib/tableschema/types/string.rb +8 -0
- data/lib/tableschema/types/time.rb +1 -0
- data/lib/tableschema/types/year.rb +34 -0
- data/lib/tableschema/types/yearmonth.rb +52 -0
- data/lib/tableschema/validate.rb +45 -29
- data/lib/tableschema/version.rb +1 -1
- data/tableschema.gemspec +2 -1
- metadata +31 -12
- data/etc/schemas/json-table-schema.json +0 -102
- data/lib/tableschema/data.rb +0 -60
- data/lib/tableschema/types/null.rb +0 -37
@@ -9,6 +9,7 @@ module TableSchema
|
|
9
9
|
def self.supported_constraints
|
10
10
|
[
|
11
11
|
'required',
|
12
|
+
'unique',
|
12
13
|
'pattern',
|
13
14
|
'enum'
|
14
15
|
]
|
@@ -19,18 +20,39 @@ module TableSchema
|
|
19
20
|
end
|
20
21
|
|
21
22
|
def cast_default(value)
|
22
|
-
|
23
|
-
JSON::Validator.validate!(geojson_schema,
|
24
|
-
|
23
|
+
parsed_value = parse_value(value)
|
24
|
+
JSON::Validator.validate!(geojson_schema, parsed_value)
|
25
|
+
parsed_value
|
25
26
|
rescue JSON::Schema::ValidationError, JSON::ParserError
|
26
27
|
raise TableSchema::InvalidGeoJSONType.new("#{value} is not valid GeoJSON")
|
27
28
|
end
|
28
29
|
|
30
|
+
def cast_topojson(value)
|
31
|
+
parsed_value = parse_value(value)
|
32
|
+
JSON::Validator.validate!(topojson_schema, parsed_value)
|
33
|
+
parsed_value
|
34
|
+
rescue JSON::Schema::ValidationError, JSON::ParserError
|
35
|
+
raise TableSchema::InvalidTopoJSONType.new("#{value} is not valid TopoJSON")
|
36
|
+
end
|
37
|
+
|
29
38
|
private
|
30
39
|
|
40
|
+
def parse_value(value)
|
41
|
+
if value.is_a?(type)
|
42
|
+
value
|
43
|
+
else
|
44
|
+
JSON.parse(value, symbolize_names: true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
31
48
|
def geojson_schema
|
32
|
-
path = File.join( File.dirname(__FILE__), "..", "..", "
|
33
|
-
|
49
|
+
path = File.join( File.dirname(__FILE__), "..", "..", "profiles", "geojson.json" )
|
50
|
+
JSON.parse(File.read(path), symbolize_names: true)
|
51
|
+
end
|
52
|
+
|
53
|
+
def topojson_schema
|
54
|
+
path = File.join( File.dirname(__FILE__), "..", "..", "profiles", "topojson.json" )
|
55
|
+
JSON.parse(File.read(path), symbolize_names: true)
|
34
56
|
end
|
35
57
|
|
36
58
|
end
|
@@ -9,6 +9,7 @@ module TableSchema
|
|
9
9
|
def self.supported_constraints
|
10
10
|
[
|
11
11
|
'required',
|
12
|
+
'geopoint',
|
12
13
|
'pattern',
|
13
14
|
'enum'
|
14
15
|
]
|
@@ -24,14 +25,14 @@ module TableSchema
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def cast_object(value)
|
27
|
-
value = JSON.parse(value) if value.is_a?(::String)
|
28
|
-
cast_array([value[
|
28
|
+
value = JSON.parse(value, symbolize_names: true) if value.is_a?(::String)
|
29
|
+
cast_array([value[:longitude], value[:latitude]])
|
29
30
|
rescue JSON::ParserError
|
30
31
|
raise TableSchema::InvalidGeoPointType.new("#{value} is not a valid geopoint")
|
31
32
|
end
|
32
33
|
|
33
34
|
def cast_array(value)
|
34
|
-
value = JSON.parse(value) if value.is_a?(::String)
|
35
|
+
value = JSON.parse(value, symbolize_names: true) if value.is_a?(::String)
|
35
36
|
value = [Float(value[0]), Float(value[1])]
|
36
37
|
check_latlng_range(value)
|
37
38
|
value
|
@@ -9,6 +9,7 @@ module TableSchema
|
|
9
9
|
def self.supported_constraints
|
10
10
|
[
|
11
11
|
'required',
|
12
|
+
'unique',
|
12
13
|
'pattern',
|
13
14
|
'enum',
|
14
15
|
'minimum',
|
@@ -20,41 +21,55 @@ module TableSchema
|
|
20
21
|
::Float
|
21
22
|
end
|
22
23
|
|
23
|
-
def currency_symbols
|
24
|
-
ISO4217::Currency.currencies.to_a.map { |c| Regexp.escape(c.last.symbol) rescue nil }.delete_if { |s| s.nil? }
|
25
|
-
end
|
26
24
|
|
27
25
|
def cast_default(value)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
case value
|
27
|
+
when type
|
28
|
+
value
|
29
|
+
when ::Integer
|
30
|
+
Float(value)
|
31
|
+
when ::String
|
32
|
+
process_string(value)
|
33
|
+
end
|
33
34
|
rescue ArgumentError
|
34
35
|
raise TableSchema::InvalidCast.new("#{value} is not a #{name}")
|
35
36
|
end
|
36
37
|
|
37
|
-
def cast_currency(value)
|
38
|
-
cast_default(value)
|
39
|
-
rescue TableSchema::InvalidCast
|
40
|
-
value = preprocess_value(value)
|
41
|
-
re = Regexp.new currency_symbols.join('|')
|
42
|
-
value.gsub!(re, '')
|
43
|
-
cast_default(value)
|
44
|
-
end
|
45
|
-
|
46
38
|
private
|
47
39
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
40
|
+
def process_string(value)
|
41
|
+
case value
|
42
|
+
when 'NaN'
|
43
|
+
Float::NAN
|
44
|
+
when '-INF'
|
45
|
+
-Float::INFINITY
|
46
|
+
when 'INF'
|
47
|
+
Float::INFINITY
|
48
|
+
else
|
49
|
+
group_char = @field.fetch(:groupChar, TableSchema::DEFAULTS[:group_char])
|
50
|
+
decimal_char = @field.fetch(:decimalChar, TableSchema::DEFAULTS[:decimal_char])
|
51
|
+
formatted_value = value.gsub(group_char, '').gsub(decimal_char, '.')
|
52
|
+
if formatted_value.match(percent_chars)
|
53
|
+
process_percent(formatted_value)
|
54
|
+
elsif @field.fetch(:currency, nil)
|
55
|
+
process_currency(formatted_value)
|
56
|
+
else
|
57
|
+
Float(formatted_value)
|
58
|
+
end
|
59
|
+
end
|
56
60
|
end
|
57
61
|
|
62
|
+
def process_percent(value)
|
63
|
+
Float(value.gsub(percent_chars, '')) / 100
|
64
|
+
end
|
65
|
+
|
66
|
+
def process_currency(value)
|
67
|
+
Float(value.gsub(@field[:currency], ''))
|
68
|
+
end
|
69
|
+
|
70
|
+
def percent_chars
|
71
|
+
/%|‰|‱|%|﹪|٪/
|
72
|
+
end
|
58
73
|
end
|
59
74
|
end
|
60
75
|
end
|
@@ -9,6 +9,7 @@ module TableSchema
|
|
9
9
|
def self.supported_constraints
|
10
10
|
[
|
11
11
|
'required',
|
12
|
+
'unique',
|
12
13
|
'pattern',
|
13
14
|
'enum',
|
14
15
|
'minLength',
|
@@ -22,7 +23,7 @@ module TableSchema
|
|
22
23
|
|
23
24
|
def cast_default(value)
|
24
25
|
return value if value.is_a?(type)
|
25
|
-
parsed = JSON.parse(value)
|
26
|
+
parsed = JSON.parse(value, symbolize_names: true)
|
26
27
|
if parsed.is_a?(Hash)
|
27
28
|
return parsed
|
28
29
|
else
|
@@ -9,6 +9,7 @@ module TableSchema
|
|
9
9
|
def self.supported_constraints
|
10
10
|
[
|
11
11
|
'required',
|
12
|
+
'unique',
|
12
13
|
'pattern',
|
13
14
|
'enum',
|
14
15
|
'minLength',
|
@@ -59,6 +60,13 @@ module TableSchema
|
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
63
|
+
def cast_binary(value)
|
64
|
+
value = cast_default(value)
|
65
|
+
Base64.strict_decode64(value)
|
66
|
+
rescue ArgumentError
|
67
|
+
raise TableSchema::InvalidBinary.new("#{value} is not a valid binary string")
|
68
|
+
end
|
69
|
+
|
62
70
|
end
|
63
71
|
end
|
64
72
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module TableSchema
|
2
|
+
module Types
|
3
|
+
class Year < Base
|
4
|
+
|
5
|
+
def name
|
6
|
+
'year'
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.supported_constraints
|
10
|
+
[
|
11
|
+
'required',
|
12
|
+
'unique',
|
13
|
+
'enum',
|
14
|
+
'minimum',
|
15
|
+
'maximum',
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
def type
|
20
|
+
::Integer
|
21
|
+
end
|
22
|
+
|
23
|
+
def cast_default(value)
|
24
|
+
cast = ::Date._strptime(value.to_s, '%Y')
|
25
|
+
unless cast.nil? || cast.include?(:leftover)
|
26
|
+
cast[:year]
|
27
|
+
else
|
28
|
+
raise TableSchema::InvalidYearType.new("#{value} is not a valid year")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module TableSchema
|
2
|
+
module Types
|
3
|
+
class YearMonth < Base
|
4
|
+
|
5
|
+
def name
|
6
|
+
'yearmonth'
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.supported_constraints
|
10
|
+
[
|
11
|
+
'required',
|
12
|
+
'unique',
|
13
|
+
'pattern',
|
14
|
+
'enum',
|
15
|
+
'minimum',
|
16
|
+
'maximum',
|
17
|
+
]
|
18
|
+
end
|
19
|
+
|
20
|
+
def type
|
21
|
+
::Hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def cast_default(value)
|
25
|
+
value = array_to_yearmonth_string(value) if value.class == ::Array
|
26
|
+
cast = ::Date._strptime(value, '%Y-%m')
|
27
|
+
unless cast.nil? || cast.include?(:leftover)
|
28
|
+
array_to_yearmonth(cast.values)
|
29
|
+
else
|
30
|
+
raise TableSchema::InvalidYearMonthType.new("#{value} is not a valid yearmonth")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def array_to_yearmonth(value_array)
|
37
|
+
{
|
38
|
+
year: value_array[0],
|
39
|
+
month: value_array[1],
|
40
|
+
}.freeze
|
41
|
+
end
|
42
|
+
|
43
|
+
def array_to_yearmonth_string(value)
|
44
|
+
if value.length != 2
|
45
|
+
raise TableSchema::InvalidYearMonthType.new("#{value} is not a valid yearmonth")
|
46
|
+
end
|
47
|
+
"#{value[0]}-#{value[1]}"
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/tableschema/validate.rb
CHANGED
@@ -1,54 +1,70 @@
|
|
1
1
|
module TableSchema
|
2
2
|
module Validate
|
3
3
|
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :errors
|
5
5
|
|
6
6
|
def load_validator!
|
7
|
-
filepath = File.join(File.dirname(__FILE__), '..', '
|
8
|
-
@
|
9
|
-
end
|
10
|
-
|
11
|
-
def valid?
|
12
|
-
validate
|
13
|
-
@messages.count == 0
|
7
|
+
filepath = File.join(File.dirname(__FILE__), '..', 'profiles', 'table-schema.json')
|
8
|
+
@profile ||= JSON.parse(File.read(filepath), symbolize_names: true)
|
14
9
|
end
|
15
10
|
|
16
11
|
def validate
|
17
|
-
@
|
12
|
+
@errors = Set.new(JSON::Validator.fully_validate(@profile, self))
|
18
13
|
check_primary_keys
|
19
14
|
check_foreign_keys
|
15
|
+
@errors.empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate!
|
19
|
+
validate
|
20
|
+
raise SchemaException.new(@errors.first) unless @errors.empty?
|
21
|
+
true
|
20
22
|
end
|
21
23
|
|
22
24
|
private
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
def check_primary_keys
|
27
|
+
return if self[:primaryKey].nil?
|
28
|
+
primary_keys.each { |pk| check_field_value(pk, 'primaryKey') }
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
add_error("A
|
31
|
+
def check_foreign_keys
|
32
|
+
return if self[:foreignKeys].nil?
|
33
|
+
self[:foreignKeys].each do |key|
|
34
|
+
if field_type_mismatch?(key)
|
35
|
+
add_error("A TableSchema `foreignKey.fields` value must be the same type as `foreignKey.reference.fields`")
|
36
|
+
end
|
37
|
+
if field_count_mismatch?(key)
|
38
|
+
add_error("A TableSchema `foreignKey.fields` must contain the same number of entries as `foreignKey.reference.fields`")
|
39
|
+
end
|
40
|
+
foreign_key_fields(key).each { |fk| check_field_value(fk, 'foreignKey.fields') }
|
41
|
+
if key.fetch(:reference).fetch(:resource).empty?
|
42
|
+
foreign_key_fields(key.fetch(:reference)).each { |fk| check_field_value(fk, 'foreignKey.reference.fields')}
|
34
43
|
end
|
35
44
|
end
|
45
|
+
end
|
36
46
|
|
37
|
-
|
38
|
-
|
47
|
+
def check_field_value(key, type)
|
48
|
+
if headers.select { |f| key == f }.count == 0
|
49
|
+
add_error("The TableSchema #{type} value `#{key}` is not found in any of the schema's field names")
|
39
50
|
end
|
51
|
+
end
|
40
52
|
|
41
|
-
|
42
|
-
|
43
|
-
|
53
|
+
def foreign_key_fields(key)
|
54
|
+
[key.fetch(:fields)].flatten
|
55
|
+
end
|
44
56
|
|
45
|
-
|
46
|
-
|
47
|
-
|
57
|
+
def field_count_mismatch?(key)
|
58
|
+
foreign_key_fields(key).count != foreign_key_fields(key.fetch(:reference)).count
|
59
|
+
end
|
48
60
|
|
49
|
-
|
50
|
-
|
51
|
-
|
61
|
+
def field_type_mismatch?(key)
|
62
|
+
key.fetch(:fields).class.name != key.fetch(:reference).fetch(:fields).class.name
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_error(error)
|
66
|
+
@errors << error
|
67
|
+
end
|
52
68
|
|
53
69
|
end
|
54
70
|
end
|
data/lib/tableschema/version.rb
CHANGED
data/tableschema.gemspec
CHANGED
@@ -24,9 +24,10 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency "pry", "~> 0.10.0"
|
25
25
|
spec.add_development_dependency "webmock", "~> 2.3.0"
|
26
26
|
spec.add_development_dependency "coveralls", "~> 0.8.13"
|
27
|
+
spec.add_development_dependency "rubocop", "~> 0.49.1"
|
27
28
|
|
28
29
|
spec.add_dependency "json-schema", "~> 2.6.0"
|
29
30
|
spec.add_dependency "uuid", "~> 2.3.8"
|
30
|
-
spec.add_dependency "currencies", "~> 0.4.2"
|
31
31
|
spec.add_dependency "tod", "~> 2.1.0"
|
32
|
+
spec.add_dependency "activesupport", "~> 5.1.0"
|
32
33
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tableschema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Open Knowledge Foundation
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 0.8.13
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.49.1
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.49.1
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: json-schema
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,33 +137,33 @@ dependencies:
|
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: 2.3.8
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
140
|
+
name: tod
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - "~>"
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
145
|
+
version: 2.1.0
|
132
146
|
type: :runtime
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
150
|
- - "~>"
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
152
|
+
version: 2.1.0
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
154
|
+
name: activesupport
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
142
156
|
requirements:
|
143
157
|
- - "~>"
|
144
158
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
159
|
+
version: 5.1.0
|
146
160
|
type: :runtime
|
147
161
|
prerelease: false
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
149
163
|
requirements:
|
150
164
|
- - "~>"
|
151
165
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
166
|
+
version: 5.1.0
|
153
167
|
description:
|
154
168
|
email:
|
155
169
|
- info@okfn.org
|
@@ -159,6 +173,7 @@ extra_rdoc_files: []
|
|
159
173
|
files:
|
160
174
|
- ".gitignore"
|
161
175
|
- ".rspec"
|
176
|
+
- ".rubocop.yml"
|
162
177
|
- ".travis.yml"
|
163
178
|
- CHANGELOG.md
|
164
179
|
- CODE_OF_CONDUCT.md
|
@@ -168,8 +183,9 @@ files:
|
|
168
183
|
- Rakefile
|
169
184
|
- bin/console
|
170
185
|
- bin/setup
|
171
|
-
-
|
172
|
-
-
|
186
|
+
- lib/profiles/geojson.json
|
187
|
+
- lib/profiles/table-schema.json
|
188
|
+
- lib/profiles/topojson.json
|
173
189
|
- lib/tableschema.rb
|
174
190
|
- lib/tableschema/constraints/constraints.rb
|
175
191
|
- lib/tableschema/constraints/enum.rb
|
@@ -179,7 +195,8 @@ files:
|
|
179
195
|
- lib/tableschema/constraints/minimum.rb
|
180
196
|
- lib/tableschema/constraints/pattern.rb
|
181
197
|
- lib/tableschema/constraints/required.rb
|
182
|
-
- lib/tableschema/
|
198
|
+
- lib/tableschema/constraints/unique.rb
|
199
|
+
- lib/tableschema/defaults.rb
|
183
200
|
- lib/tableschema/exceptions.rb
|
184
201
|
- lib/tableschema/field.rb
|
185
202
|
- lib/tableschema/helpers.rb
|
@@ -193,14 +210,16 @@ files:
|
|
193
210
|
- lib/tableschema/types/boolean.rb
|
194
211
|
- lib/tableschema/types/date.rb
|
195
212
|
- lib/tableschema/types/datetime.rb
|
213
|
+
- lib/tableschema/types/duration.rb
|
196
214
|
- lib/tableschema/types/geojson.rb
|
197
215
|
- lib/tableschema/types/geopoint.rb
|
198
216
|
- lib/tableschema/types/integer.rb
|
199
|
-
- lib/tableschema/types/null.rb
|
200
217
|
- lib/tableschema/types/number.rb
|
201
218
|
- lib/tableschema/types/object.rb
|
202
219
|
- lib/tableschema/types/string.rb
|
203
220
|
- lib/tableschema/types/time.rb
|
221
|
+
- lib/tableschema/types/year.rb
|
222
|
+
- lib/tableschema/types/yearmonth.rb
|
204
223
|
- lib/tableschema/validate.rb
|
205
224
|
- lib/tableschema/version.rb
|
206
225
|
- tableschema.gemspec
|