sportdb 1.9.10 → 1.9.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ed1aa660c6f5bcc10d6197bbf48494c6fe6e0e3f
4
- data.tar.gz: 6ab3685c798fff2e82e94af70b5d8c9e048d8db2
3
+ metadata.gz: 68f64d57578e9dffc8a1f676e0d7771fb486e7ef
4
+ data.tar.gz: 02d84695cdcb3b1fea7269db822292f9003e7305
5
5
  SHA512:
6
- metadata.gz: a2f5811eb0d21e5f3ec58df3c9c087998017fc716a41b4105c96a31164fed79018e922367a14163dac30ced4151ba6bb93ed006c5bb8e270f5fd41458fd93043
7
- data.tar.gz: dd6220cddf7565946b24b2e471efba17e93c29f47366abed585bd3bea4d3556190d557ebcbf00bdc64fe6597e98e5e3e53eee144bbb6772ea8f6809dfc94167c
6
+ metadata.gz: 1c1da39819f4b5921ea03598f0bce3b129e0219fdd2016ebad21626f9667ed50b0655302f8c251eda3a0c30b1c3dfbce7d113735f7db0bf9b0ae463c47a17ede
7
+ data.tar.gz: d3eedae5177bb1708a60bc03267f8672e5c290707d98ceb1338b509f144d2a4a1ba51c626ae2f72b536a9eb891f95aa953123599cfb508a29585891835f38645
@@ -13,6 +13,8 @@ config/fixtures/ro.yml
13
13
  data/seasons.txt
14
14
  data/setups/all.txt
15
15
  lib/sportdb.rb
16
+ lib/sportdb/builder/builder.rb
17
+ lib/sportdb/builder/dataset.rb
16
18
  lib/sportdb/calc.rb
17
19
  lib/sportdb/cli/main.rb
18
20
  lib/sportdb/cli/opts.rb
@@ -125,6 +127,7 @@ test/data/world-cup/teams_1962.txt
125
127
  test/data/world-cup/teams_1974.txt
126
128
  test/helper.rb
127
129
  test/test_assoc_reader.rb
130
+ test/test_builder.rb
128
131
  test/test_changes.rb
129
132
  test/test_cursor.rb
130
133
  test/test_date.rb
@@ -8,6 +8,9 @@
8
8
  # core and stlibs (note: get included via worlddb gem; see worlddb gem/lib)
9
9
 
10
10
 
11
+ require 'fileutils'
12
+
13
+
11
14
  # rubygems / 3rd party libs
12
15
 
13
16
  require 'active_record'
@@ -110,6 +113,10 @@ require 'sportdb/deleter'
110
113
  require 'sportdb/stats'
111
114
 
112
115
 
116
+ require 'sportdb/builder/dataset'
117
+ require 'sportdb/builder/builder'
118
+
119
+
113
120
  module SportDb
114
121
 
115
122
  def self.config_path
@@ -152,6 +159,12 @@ module SportDb
152
159
  reader.load_setup( setup )
153
160
  end
154
161
 
162
+ def self.read_setup_from_zip( zip_name, setup, include_path, opts={} ) ## todo/check - use a better (shorter) name ??
163
+ reader = ZipReader.new( zip_name, include_path, opts )
164
+ reader.load_setup( setup )
165
+ reader.close
166
+ end
167
+
155
168
  def self.read_all( include_path ) # convenience helper
156
169
  read_setup( 'setups/all', include_path )
157
170
  end
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+
3
+ module SportDb
4
+
5
+ class Builder
6
+
7
+ include LogUtils::Logging
8
+
9
+ def initialize()
10
+ @datasets = []
11
+ end
12
+
13
+ def self.load_file( path )
14
+ code = File.read_utf8( path )
15
+ self.load( code )
16
+ end
17
+
18
+ def self.load( code )
19
+ builder = Builder.new
20
+ builder.instance_eval( code )
21
+ builder
22
+ end
23
+
24
+
25
+ def football( name, opts={} )
26
+ logger.info( "[builder] add football-dataset '#{@name}'" )
27
+ @datasets << FootballDataset.new( name, opts )
28
+ end
29
+
30
+ def world( name, opts={} )
31
+ logger.info( "[builder] add world-dataset '#{@name}'" )
32
+ @datasets << WorldDataset.new( name, opts )
33
+ end
34
+
35
+
36
+ def run()
37
+ logger.info( "[builder] begin - run" )
38
+ download() # step 1 - download zips for datasets
39
+ read() # step 2 - read in datasets from zips
40
+ logger.info( "[builder] end - run" )
41
+ end
42
+
43
+ def download()
44
+ logger.info( "[builder] dowload" )
45
+ @datasets.each do |dataset|
46
+ dataset.download()
47
+ end
48
+ end
49
+
50
+ def read()
51
+ logger.info( "[builder] read" )
52
+ @datasets.each do |dataset|
53
+ dataset.read()
54
+ end
55
+ end
56
+
57
+ end # class Builder
58
+ end # module SportDb
@@ -0,0 +1,90 @@
1
+ # encoding: utf-8
2
+
3
+ module SportDb
4
+
5
+ class Dataset
6
+ include LogUtils::Logging
7
+
8
+ def initialize( name, opts={} )
9
+ @name = name
10
+ @opts = opts
11
+ end
12
+
13
+ def setup()
14
+ value = @opts[:setup] || 'all'
15
+ "setups/#{value}"
16
+ end
17
+
18
+ def remote_zip_url() # remote zip url
19
+ "https://github.com/#{@name}/archive/master.zip"
20
+ end
21
+
22
+ def local_zip_name()
23
+ ### note: replace / in name w/ --I--
24
+ ## e.g. flatten the filename, that is, do NOT include any folders
25
+ @name.gsub('/', '--I--') # note: will NOT include/return .zip extension
26
+ end
27
+
28
+ def local_zip_root()
29
+ "./tmp"
30
+ end
31
+
32
+ def local_zip_path() # local zip path
33
+ "#{local_zip_root}/#{local_zip_name}.zip"
34
+ end
35
+
36
+
37
+ def download()
38
+ logger.info( "[builder] download dataset '#{@name}'" )
39
+ logger.info( "[builder] from '#{remote_zip_url}'" )
40
+ logger.info( "[builder] to '#{local_zip_path}'..." )
41
+
42
+ download_blob( remote_zip_url, local_zip_path )
43
+ end
44
+
45
+ ####
46
+ # download tasks for zips
47
+ def download_blob( url, dest )
48
+ logger.info "downloading #{url} to #{dest}..."
49
+
50
+ ## make sure dest path exists
51
+ dest_p = File.dirname( dest )
52
+ FileUtils.mkdir_p( dest_p ) unless File.exists?( dest_p ) ## use Dir.exists?? why? why not??
53
+
54
+ worker = Fetcher::Worker.new
55
+ worker.copy( url, dest )
56
+ ## print some file stats
57
+ logger.debug " size: #{File.size(dest)} bytes"
58
+ end
59
+
60
+ end # class Dataset
61
+
62
+
63
+ class WorldDataset < Dataset
64
+
65
+ def initialize( name, opts={} )
66
+ super( name, opts )
67
+ end
68
+
69
+ def read()
70
+ logger.info( "[builder] read world-dataset '#{@name}', '#{setup}'" )
71
+
72
+ WorldDb.read_setup_from_zip( local_zip_name(), setup(), local_zip_root(), { skip_tags: true } )
73
+ end
74
+ end # class WorldDataset
75
+
76
+ class FootballDataset < Dataset
77
+
78
+ def initialize( name, opts={} )
79
+ super( name, opts )
80
+ end
81
+
82
+ def read()
83
+ logger.info( "[builder] read football-dataset '#{@name}', '#{setup}'" )
84
+
85
+ SportDb.read_setup_from_zip( local_zip_name(), setup(), local_zip_root() )
86
+ end
87
+ end # class FootballDataset
88
+
89
+
90
+ end # module SportDb
@@ -108,6 +108,34 @@ command [:create] do |c|
108
108
  end # command create
109
109
 
110
110
 
111
+ desc "Build DB (download/create/load); use ./Datafile - zips get downloaded to ./tmp"
112
+ command [:build,:b] do |c|
113
+
114
+ c.action do |g,o,args|
115
+
116
+ builder = SportDb::Builder.load_file( './Datafile' )
117
+ builder.download # builder step 1 - download all datasets/zips
118
+
119
+ connect_to_db( opts )
120
+
121
+ LogDb.create
122
+ ConfDb.create
123
+ TagDb.create
124
+ WorldDb.create
125
+ PersonDb.create
126
+ SportDb.create
127
+
128
+ SportDb.read_builtin # e.g. seasons.txt etc
129
+
130
+ builder.read # builder step 2 - read all datasets
131
+
132
+ puts 'Done.'
133
+ end # action
134
+ end # command setup
135
+
136
+
137
+
138
+
111
139
  desc "Create DB schema 'n' load all world and sports data"
112
140
  arg_name 'NAME' # optional setup profile name
113
141
  command [:setup,:s] do |c|
@@ -5,7 +5,160 @@ module SportDb
5
5
 
6
6
  class ZipReader < ReaderBase
7
7
 
8
+ def initialize( name, include_path, opts = {} )
8
9
 
10
+ ## todo/fix: make include_path an opts (included in opts?) - why? why not??
11
+
12
+ path = "#{include_path}/#{name}.zip"
13
+ ## todo: check if zip exists
14
+
15
+ @zip_file = Zip::File.open( path ) ## NOTE: do NOT create if file is missing; let it crash
16
+
17
+ ### allow prefix (path) in name
18
+ ### e.g. assume all files relative to setup manifest
19
+ ## e.g. at-austria-master/setups/all.txt or
20
+ ## be-belgium-master/setups/all.txt
21
+ ## for
22
+ ## setups/all.txt
23
+ ###
24
+ ## will get (re)set w/ fixture/setup reader
25
+ ##
26
+ ## todo/fix: change/rename to @relative_path ?? - why? why not?
27
+ @zip_prefix = ''
28
+ end
29
+
30
+ def close
31
+ ## todo/check: add a close method - why? why not ???
32
+ @zip_file.close
33
+ end
34
+
35
+
36
+ def create_fixture_reader( name )
37
+ ## e.g. pass in => setups/all or setups/test etc. e.g. w/o .txt extension
38
+ query = "**/#{name}.txt"
39
+
40
+ ## note: returns an array of Zip::Entry
41
+ candidates = @zip_file.glob( query )
42
+ pp candidates
43
+
44
+ ## use first candidates entry as match
45
+ ## todo/fix: issue warning if more than one entries/matches!!
46
+
47
+ ## get fullpath e.g. at-austria-master/setups/all.txt
48
+ path = candidates[0].name
49
+ logger.debug " zip entry path >>#{path}<<"
50
+
51
+ ## cut-off at-austria-master/ NOTE: includes trailing slash (if present)
52
+ ## logger.debug " path.size #{path.size} >>#{path}<<"
53
+ ## logger.debug " name.size #{name.size+4} >>#{name}<<"
54
+
55
+ ## note: add +4 for extension (.txt)
56
+ @zip_prefix = path[ 0...(path.size-(name.size+4)) ]
57
+ logger.debug " zip entry prefix >>#{@zip_prefix}<<"
58
+
59
+ logger.info "parsing data in zip '#{name}' (#{path})..."
60
+
61
+ FixtureReader.from_zip( @zip_file, path )
62
+ end
63
+
64
+ def create_club_squad_reader( name, more_attribs={} )
65
+ path = name_to_zip_entry_path( name )
66
+
67
+ logger.info "parsing data in zip (club squad) '#{name}' (#{path})..."
68
+ ClubSquadReader.from_zip( @zip_file, path, more_attribs )
69
+ end
70
+
71
+ def create_national_team_squad_reader( name, more_attribs={} )
72
+ path = name_to_zip_entry_path( name )
73
+
74
+ logger.info "parsing data in zip (national team squad) '#{name}' (#{path})..."
75
+ NationalTeamSquadReader.from_zip( @zip_file, path, more_attribs )
76
+ end
77
+
78
+ def create_season_reader( name )
79
+ path = name_to_zip_entry_path( name )
80
+
81
+ logger.info "parsing data in zip (season) '#{name}' (#{path})..."
82
+ SeasonReader.from_zip( @zip_file, path )
83
+ end
84
+
85
+ def create_assoc_reader( name )
86
+ path = name_to_zip_entry_path( name )
87
+
88
+ logger.info "parsing data in zip (assoc) '#{name}' (#{path})..."
89
+ AssocReader.from_zip( @zip_file, path )
90
+ end
91
+
92
+ def create_ground_reader( name, more_attribs={} )
93
+ path = name_to_zip_entry_path( name )
94
+
95
+ logger.info "parsing data in zip (ground) '#{name}' (#{path})..."
96
+ GroundReader.from_zip( @zip_file, path, more_attribs )
97
+ end
98
+
99
+ def create_league_reader( name, more_attribs={} )
100
+ path = name_to_zip_entry_path( name )
101
+
102
+ logger.info "parsing data in zip (league) '#{name}' (#{path})..."
103
+ LeagueReader.from_zip( @zip_file, path, more_attribs )
104
+ end
105
+
106
+ def create_team_reader( name, more_attribs={} )
107
+ path = name_to_zip_entry_path( name )
108
+
109
+ logger.info "parsing data in zip (team) '#{name}' (#{path})..."
110
+ TeamReader.from_zip( @zip_file, path, more_attribs )
111
+ end
112
+
113
+ def create_event_reader( name, more_attribs={} )
114
+ path = name_to_zip_entry_path( name, '.yml' ) ## NOTE: use .yml extension
115
+
116
+ logger.info "parsing data in zip (event) '#{name}' (#{path})..."
117
+ EventReader.from_zip( @zip_file, path, more_attribs )
118
+ end
119
+
120
+ def create_game_reader( name, more_attribs={} )
121
+ ## NOTE: pass in .yml as path (that is, event config!!!!)
122
+ path = name_to_zip_entry_path( name, '.yml' ) ## NOTE: use .yml extension
123
+
124
+ logger.info "parsing data in zip (fixture) '#{name}' (#{path})..."
125
+ GameReader.from_zip( @zip_file, path, more_attribs )
126
+ end
127
+
128
+
129
+ def create_person_reader( name, more_attribs={} )
130
+ ## fix-fix-fix: change to new format e.g. from_file, from_zip etc!!!
131
+ ## reader = PersonDb::PersonReader.new( include_path )
132
+ # reader.read( name, country_id: country.id )
133
+ end
134
+
135
+ private
136
+
137
+ def path_to_real_path( path )
138
+ # map name to name_real_path
139
+ # name might include !/ for virtual path (gets cut off)
140
+ # e.g. at-austria!/w-wien/beers becomse w-wien/beers
141
+ pos = path.index( '!/')
142
+ if pos.nil?
143
+ path # not found; real path is the same as name
144
+ else
145
+ # cut off everything until !/ e.g.
146
+ # at-austria!/w-wien/beers becomes
147
+ # w-wien/beers
148
+ path[ (pos+2)..-1 ]
149
+ end
150
+ end
151
+
152
+ def name_to_zip_entry_path( name, extension='.txt' )
153
+ path = "#{name}#{extension}"
154
+
155
+ real_path = path_to_real_path( path )
156
+
157
+ # NOTE: add possible zip entry prefix path
158
+ # (if present includes trailing slash e.g. /)
159
+ entry_path = "#{@zip_prefix}#{real_path}"
160
+ entry_path
161
+ end
9
162
 
10
163
  end # class ZipReader
11
164
 
@@ -11,8 +11,15 @@ class AssocReader
11
11
  # e.g. lets you use Usage instead of Model::Usage
12
12
  include Models
13
13
 
14
+
14
15
  def self.from_zip( zip_file, entry_path, more_attribs={} )
15
- ## to be done
16
+ ## get text content from zip
17
+ entry = zip_file.find_entry( entry_path )
18
+
19
+ text = entry.get_input_stream().read()
20
+ text = text.force_encoding( Encoding::UTF_8 )
21
+
22
+ self.from_string( text, more_attribs )
16
23
  end
17
24
 
18
25
  def self.from_file( path, more_attribs={} )
@@ -15,7 +15,15 @@ class EventReader
15
15
  attr_reader :fixtures # fixtures/sources entry from event config
16
16
 
17
17
  def self.from_zip( zip_file, entry_path, more_attribs={} )
18
- ## to be done
18
+ ## get text content from zip
19
+ entry = zip_file.find_entry( entry_path )
20
+
21
+ text = entry.get_input_stream().read()
22
+ text = text.force_encoding( Encoding::UTF_8 )
23
+
24
+ config = File.basename( entry_path ) # name a of .yml file
25
+
26
+ self.from_string( text, config, more_attribs )
19
27
  end
20
28
 
21
29
  def self.from_file( path, more_attribs={} )
@@ -16,9 +16,46 @@ class GameReader
16
16
 
17
17
  include FixtureHelpers
18
18
 
19
-
20
19
  def self.from_zip( zip_file, entry_path, more_attribs={} )
21
- ## to be done
20
+
21
+ logger = LogKernel::Logger.root
22
+
23
+ reader = EventReader.from_zip( zip_file, entry_path )
24
+ reader.read()
25
+
26
+ event = reader.event ## was fetch_event( name )
27
+ fixtures = reader.fixtures ## was fetch_event_fixtures( name )
28
+
29
+ if fixtures.empty?
30
+ ## logger.warn "no fixtures found for event - >#{name}<; assume fixture name is the same as event"
31
+ ## change extension from .yml to .txt
32
+ fixtures_with_path = [ entry_path.sub('.yml','.txt') ]
33
+ else
34
+ ## add path to fixtures (use path from event e.g)
35
+ # - bl + at-austria!/2012_13/bl -> at-austria!/2012_13/bl
36
+ # - bl_ii + at-austria!/2012_13/bl -> at-austria!/2012_13/bl_ii
37
+
38
+ dir = File.dirname( entry_path ) # use dir for fixtures
39
+
40
+ fixtures_with_path = fixtures.map do |fx|
41
+ fx_new = "#{dir}/#{fx}.txt" # add path upfront
42
+ logger.debug "fx: #{fx_new} | >#{fx}< + >#{dir}<"
43
+ fx_new
44
+ end
45
+ end
46
+
47
+ ## fix-fix-fix: change file extension to ??
48
+ text_ary = []
49
+ fixtures_with_path.each do |fixture_path|
50
+ entry = zip_file.find_entry( fixture_path )
51
+
52
+ text = entry.get_input_stream().read()
53
+ text = text.force_encoding( Encoding::UTF_8 )
54
+
55
+ text_ary << text
56
+ end
57
+
58
+ self.from_string( event, text_ary, more_attribs )
22
59
  end
23
60
 
24
61
  def self.from_file( path, more_attribs={} )
@@ -12,7 +12,13 @@ class GroundReader
12
12
  include Models
13
13
 
14
14
  def self.from_zip( zip_file, entry_path, more_attribs={} )
15
- ## to be done
15
+ ## get text content from zip
16
+ entry = zip_file.find_entry( entry_path )
17
+
18
+ text = entry.get_input_stream().read()
19
+ text = text.force_encoding( Encoding::UTF_8 )
20
+
21
+ self.from_string( text, more_attribs )
16
22
  end
17
23
 
18
24
  def self.from_file( path, more_attribs={} )
@@ -13,7 +13,13 @@ class LeagueReader
13
13
 
14
14
 
15
15
  def self.from_zip( zip_file, entry_path, more_attribs={} )
16
- ## to be done
16
+ ## get text content from zip
17
+ entry = zip_file.find_entry( entry_path )
18
+
19
+ text = entry.get_input_stream().read()
20
+ text = text.force_encoding( Encoding::UTF_8 )
21
+
22
+ self.from_string( text, more_attribs )
17
23
  end
18
24
 
19
25
  def self.from_file( path, more_attribs={} )
@@ -13,7 +13,13 @@ class SeasonReader
13
13
 
14
14
 
15
15
  def self.from_zip( zip_file, entry_path )
16
- ## to be done
16
+ ## get text content from zip
17
+ entry = zip_file.find_entry( entry_path )
18
+
19
+ text = entry.get_input_stream().read()
20
+ text = text.force_encoding( Encoding::UTF_8 )
21
+
22
+ self.from_string( text )
17
23
  end
18
24
 
19
25
  def self.from_file( path )
@@ -23,7 +23,13 @@ class ClubSquadReader
23
23
 
24
24
 
25
25
  def self.from_zip( zip_file, entry_path, more_attribs={} )
26
- ## to be done
26
+ ## get text content from zip
27
+ entry = zip_file.find_entry( entry_path )
28
+
29
+ text = entry.get_input_stream().read()
30
+ text = text.force_encoding( Encoding::UTF_8 )
31
+
32
+ self.from_string( text, more_attribs )
27
33
  end
28
34
 
29
35
  def self.from_file( path, more_attribs={} )
@@ -20,7 +20,13 @@ class NationalTeamSquadReader
20
20
 
21
21
 
22
22
  def self.from_zip( zip_file, entry_path, more_attribs={} )
23
- ## to be done
23
+ ## get text content from zip
24
+ entry = zip_file.find_entry( entry_path )
25
+
26
+ text = entry.get_input_stream().read()
27
+ text = text.force_encoding( Encoding::UTF_8 )
28
+
29
+ self.from_string( text, more_attribs )
24
30
  end
25
31
 
26
32
  def self.from_file( path, more_attribs={} )
@@ -12,7 +12,13 @@ class TeamReader
12
12
  include Models
13
13
 
14
14
  def self.from_zip( zip_file, entry_path, more_attribs={} )
15
- ## to be done
15
+ ## get text content from zip
16
+ entry = zip_file.find_entry( entry_path )
17
+
18
+ text = entry.get_input_stream().read()
19
+ text = text.force_encoding( Encoding::UTF_8 )
20
+
21
+ self.from_string( text, more_attribs )
16
22
  end
17
23
 
18
24
  def self.from_file( path, more_attribs={} )
@@ -3,7 +3,7 @@ module SportDb
3
3
 
4
4
  MAJOR = 1 ## todo: namespace inside version or something - why? why not??
5
5
  MINOR = 9
6
- PATCH = 10
6
+ PATCH = 11
7
7
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
8
 
9
9
  def self.version
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_builder.rb
6
+
7
+ require 'helper'
8
+
9
+ class TestBuilder < MiniTest::Test
10
+
11
+ def test_builder
12
+ code =<<EOS
13
+ ## comments
14
+
15
+ world 'openmundi/world.db', setup: 'countries'
16
+
17
+ football 'openfootball/national-teams' ## NOTE: default is setup: 'all'
18
+
19
+ ### todo/fix: download archive only once(!!) even if included more than once
20
+ ## football 'openfootball/world-cup', setup: '2014_quali'
21
+
22
+ football 'openfootball/world-cup', setup: '2014'
23
+
24
+ ## more comments
25
+
26
+ EOS
27
+
28
+ builder = SportDb::Builder.load( code )
29
+ ## builder.run
30
+ ## builder.download
31
+ builder.read
32
+
33
+ assert true # if we get here - test success
34
+ end
35
+
36
+ end # class TestBuilder
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sportdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.10
4
+ version: 1.9.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-22 00:00:00.000000000 Z
11
+ date: 2014-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: props
@@ -260,6 +260,8 @@ files:
260
260
  - data/seasons.txt
261
261
  - data/setups/all.txt
262
262
  - lib/sportdb.rb
263
+ - lib/sportdb/builder/builder.rb
264
+ - lib/sportdb/builder/dataset.rb
263
265
  - lib/sportdb/calc.rb
264
266
  - lib/sportdb/cli/main.rb
265
267
  - lib/sportdb/cli/opts.rb
@@ -372,6 +374,7 @@ files:
372
374
  - test/data/world-cup/teams_1974.txt
373
375
  - test/helper.rb
374
376
  - test/test_assoc_reader.rb
377
+ - test/test_builder.rb
375
378
  - test/test_changes.rb
376
379
  - test/test_cursor.rb
377
380
  - test/test_date.rb
@@ -435,6 +438,7 @@ test_files:
435
438
  - test/test_round_def.rb
436
439
  - test/test_utils.rb
437
440
  - test/test_reader_from_string.rb
441
+ - test/test_builder.rb
438
442
  - test/test_round_header.rb
439
443
  - test/test_round_auto.rb
440
444
  - test/test_goals.rb