fbtok 0.4.2 → 0.5.0

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
  SHA256:
3
- metadata.gz: 0bd9a1ff623cc7049c87db9b8344799d9ee49294bf1cd8f2a48cd57886fd0b89
4
- data.tar.gz: 35acfef6ccd67319d218e8dd849e3772042d8190afe786f73ba98fa19ca2418b
3
+ metadata.gz: a1df323dd41b041e34646d3df3fb90ded24707020ff8cddc90af689f2f3d33d8
4
+ data.tar.gz: c023d5844a069b4c829390e80ea2b69503809d361357df27a0e87d4ee80e336a
5
5
  SHA512:
6
- metadata.gz: 20054a913668ac69f58bc17ebbc4bdc6de6528639f64a52b60925e87129f05fbd9bfe4a87c9ea8be55bf0d5010280e0fdf2f56b8b1b892b9f4744d99aa66239b
7
- data.tar.gz: c7980b69a62273c6fffd4c7025ccb086a96070ee8dff51248fab1ddf08ef2625de467e646c4496570f163519d88985e06698c1452e639419c629521320bc26c5
6
+ metadata.gz: 7d7759e09847da4650bc008c12a5a9c52702eb30567495a2e7667a324388203db4f2a7bba6a4ed0eea8a72a2ab211b01ca70b12e6a421026dfcf09fc024b64b2
7
+ data.tar.gz: fb1673e6b654fa8fa781844534de93c5ff913b0fd7c1c828c12319cf7b22de038b5e5f3a97a9b33a6a9d3a72fd8505c6c906e4a409aff23c140589f753f80123
data/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
- ### 0.4.2
1
+ ### 0.5.0
2
2
  ### 0.0.1 / 2025-01-02
3
3
 
4
4
  * Everything is new. First release.
data/Manifest.txt CHANGED
@@ -12,4 +12,6 @@ lib/fbtok/fbquick.rb
12
12
  lib/fbtok/fbtok.rb
13
13
  lib/fbtok/fbtree.rb
14
14
  lib/fbtok/fbx.rb
15
+ lib/fbtok/filepack.rb
15
16
  lib/fbtok/pathspec.rb
17
+ lib/fbtok/pathspec_report.rb
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'hoe'
2
2
 
3
3
 
4
4
  Hoe.spec 'fbtok' do
5
- self.version = '0.4.2'
5
+ self.version = '0.5.0'
6
6
 
7
7
  self.summary = "fbtok - football.txt lint tools incl. tokenizer, parser & more"
8
8
  self.description = summary
@@ -19,7 +19,7 @@ Hoe.spec 'fbtok' do
19
19
  self.licenses = ['Public Domain']
20
20
 
21
21
  self.extra_deps = [
22
- ['sportdb-parser', '>= 0.7.1'],
22
+ ['sportdb-parser', '>= 0.7.2'],
23
23
  ['sportdb-quick', '>= 0.7.0'],
24
24
  ]
25
25
 
data/lib/fbtok/fbquick.rb CHANGED
@@ -54,10 +54,20 @@ end
54
54
  specs = if opts[:file]
55
55
  read_pathspecs( opts[:file] )
56
56
  else
57
- args = ['/sports/openfootball/euro/2021--europe/euro.txt',
58
- '/sports/openfootball/euro/2024--germany/euro.txt'] if args.empty?
59
-
60
- build_pathspecs( args )
57
+ ## check for filepack
58
+ ##
59
+ ## fix-fix-fix
60
+ ## add tool specific filepack
61
+ ## e.g. filepack.quik|quick.txt or such
62
+ ## to match first??
63
+ ## check a list of names!!
64
+ filepack = if File.file?( './filepack.txt')
65
+ read_filepack( './filepack.txt' )
66
+ else
67
+ nil
68
+ end
69
+
70
+ build_pathspecs( args, filepack: filepack )
61
71
  end
62
72
 
63
73
  pp specs
data/lib/fbtok/fbtok.rb CHANGED
@@ -58,10 +58,14 @@ end
58
58
  specs = if opts[:file]
59
59
  read_pathspecs( opts[:file] )
60
60
  else
61
- args = ['/sports/openfootball/euro/2021--europe/euro.txt',
62
- '/sports/openfootball/euro/2024--germany/euro.txt'] if args.empty?
63
-
64
- build_pathspecs( args )
61
+ ## check for filepack
62
+ filepack = if File.file?( './filepack.txt')
63
+ read_filepack( './filepack.txt' )
64
+ else
65
+ nil
66
+ end
67
+
68
+ build_pathspecs( args, filepack: filepack )
65
69
  end
66
70
 
67
71
 
@@ -82,11 +86,20 @@ specs.each_with_index do |rec,i|
82
86
  tokens, more_errors = lexer.tokenize_with_errors
83
87
 
84
88
  ####
85
- ## todo - report error on empty file (no tokens!!!)
89
+ ## todo - report error on empty file (no tokens!!!) - why? why not?
86
90
 
87
91
  puts " #{tokens.size} token(s)"
88
92
 
89
- errors += more_errors if more_errors.size > 0
93
+ if more_errors.size > 0
94
+ ## note - auto-add filename to errors
95
+ more_errors.each do |msg|
96
+ ###
97
+ ### errors << [ path, *msg ] # note: use splat (*) to add extra values (starting with msg)
98
+ errors << [path, msg]
99
+ end
100
+ end
101
+
102
+
90
103
  end
91
104
 
92
105
  if errors.size > 0
data/lib/fbtok/fbtree.rb CHANGED
@@ -58,10 +58,14 @@ end
58
58
  specs = if opts[:file]
59
59
  read_pathspecs( opts[:file] )
60
60
  else
61
- args = ['/sports/openfootball/euro/2021--europe/euro.txt',
62
- '/sports/openfootball/euro/2024--germany/euro.txt'] if args.empty?
63
-
64
- build_pathspecs( args )
61
+ ## check for filepack
62
+ filepack = if File.file?( './filepack.txt')
63
+ read_filepack( './filepack.txt' )
64
+ else
65
+ nil
66
+ end
67
+
68
+ build_pathspecs( args, filepack: filepack )
65
69
  end
66
70
 
67
71
 
@@ -81,7 +85,14 @@ specs.each_with_index do |rec,i|
81
85
 
82
86
  dump_tree_stats( tree )
83
87
 
84
- errors += parser.errors if parser.errors?
88
+ if parser.errors?
89
+ ## note - auto-add filename to errors
90
+ parser.errors.each do |msg|
91
+ ###
92
+ ### errors << [ path, *msg ] # note: use splat (*) to add extra values (starting with msg)
93
+ errors << [path, msg]
94
+ end
95
+ end
85
96
  end
86
97
 
87
98
 
data/lib/fbtok/fbx.rb CHANGED
@@ -54,8 +54,8 @@ end
54
54
 
55
55
 
56
56
  args = [
57
- '../../../openfootball/euro/2021--europe/euro.txt',
58
- '../../../openfootball/euro/2024--germany/euro.txt',
57
+ '/sports/openfootball/euro/2021--europe/euro.txt',
58
+ '/sports/openfootball/euro/2024--germany/euro.txt',
59
59
  ] if args.empty?
60
60
 
61
61
  pp args
@@ -0,0 +1,63 @@
1
+ ###################
2
+ ##
3
+ ## quick and dirty format for filepacks
4
+ ## that is, named list of files
5
+ ##
6
+ ## note - space indent(ation) does NOT matter
7
+ ##
8
+
9
+
10
+
11
+ ## PACK eng|en
12
+ ## add NAME eng|en - why? why not?
13
+ ##
14
+ ## change to FILEPACK_NAME - why? why not?
15
+ FILEPACK_HEADER_RE = %r{\A
16
+ (?: PACK ) [ ]+
17
+ (?<header> .+?) ## note - use non-greedy
18
+ \z}x
19
+
20
+ ## DIR /sports/openfootball
21
+ ## CD /sports/openfootball -- keep - why? why not?
22
+ FILEPACK_DIR_RE = %r{\A
23
+ (?: DIR|CD ) [ ]+
24
+ (?<dir> .+? ) ## note - use non-greedy
25
+
26
+ \z}x
27
+
28
+
29
+
30
+ def parse_filepack( txt )
31
+ h={}
32
+ recs = nil
33
+ basedir = nil
34
+
35
+ txt.each_line do |line|
36
+ line = line.strip
37
+
38
+ next if line.start_with?('#') || line.empty?
39
+
40
+ break if line == '__END__'
41
+
42
+
43
+ if m=FILEPACK_HEADER_RE.match(line)
44
+ keys = m[:header].strip.split( /[ ]*\|[ ]*/ )
45
+ basedir = nil
46
+ recs = []
47
+ ## note - normalize keys for now (always downcase)
48
+ keys.each {|key| h[key.downcase] = recs }
49
+ elsif m=FILEPACK_DIR_RE.match(line)
50
+ basedir = m[:dir].strip
51
+ else
52
+ file = basedir ? File.join( basedir, line ) : line
53
+ recs << file
54
+ end
55
+ end
56
+
57
+ h
58
+ end
59
+
60
+
61
+ def read_filepack( path )
62
+ parse_filepack( read_text( path ))
63
+ end
@@ -1,13 +1,13 @@
1
1
 
2
2
 
3
3
  module SportDb
4
-
5
4
  class Pathspec
6
5
 
7
6
  def self.debug=(value) @@debug = value; end
8
7
  def self.debug?() @@debug ||= false; end ## note: default is FALSE
9
8
 
10
9
 
10
+
11
11
  SEASON_RE = %r{ (?:
12
12
  (?<season>\d{4}-\d{2})
13
13
  | (?<season>\d{4})
@@ -62,9 +62,6 @@ class Pathspec
62
62
  ## but starting filename e.g. 2024_friendlies.txt or 2024-25_bundesliga.txt
63
63
 
64
64
 
65
- def self._norm_seasons( seasons )
66
- seasons.map {|season| Season(season) }
67
- end
68
65
 
69
66
 
70
67
  ## todo/check - rename to glob or expand or such - why? why not?
@@ -75,22 +72,30 @@ end
75
72
 
76
73
 
77
74
  def self._find( path, seasons: nil )
75
+ ##
76
+ ## note - only if seasons filter is turn on
77
+ ## MATCH_RE gets used!!!
78
+ ## otherwise generic **/*.txt
79
+ ##
80
+ ## note - the ignore/exlude filter always gets used/applied for now
81
+
82
+
78
83
  ## check - rename dir
79
84
  ## use root_dir or work_dir or cd or such - why? why not?
80
85
 
81
-
82
86
  ## note: normalize path - use File.expand_path ??
83
87
  ## change all backslash to slash for now
84
88
  ## path = path.gsub( "\\", '/' )
85
- path = File.expand_path( path )
89
+ fullpath = File.expand_path( path )
86
90
 
87
91
  ####
88
92
  ## note - make sure path exists; raise error if not
89
- raise Errno::ENOENT, "No such directory - #{path})" unless Dir.exist?( path )
93
+ raise Errno::ENOENT, "No such directory - #{path})" unless Dir.exist?( fullpath )
90
94
 
91
95
 
92
96
  if seasons && seasons.size > 0
93
- seasons = _norm_seasons( seasons ) ## norm seasons (string, integer => Season obj)
97
+ ## norm seasons (string, integer => Season obj)
98
+ seasons = seasons.map {|season| Season(season) }
94
99
  end
95
100
 
96
101
 
@@ -99,41 +104,45 @@ def self._find( path, seasons: nil )
99
104
  ## (normally excluded with just *)
100
105
  ## was: Dir.glob( "#{path}/**/{*,.*}.txt" )
101
106
 
102
- candidates = Dir.glob( "#{path}/**/*.txt" )
107
+ candidates = Dir.glob( "#{fullpath}/**/*.txt" )
103
108
  ## pp candidates
104
109
 
105
110
 
106
111
  datafiles = []
107
112
  candidates.each do |candidate|
108
- if m = MATCH_RE.match( candidate )
109
113
 
110
- ## check for seasons filter
111
- next if seasons && seasons.size > 0 &&
112
- !seasons.include?( Season.parse( m[:season] ))
114
+ ## (i) check for (optional) seasons filter
115
+ if seasons && seasons.size > 0
116
+ if m=MATCH_RE.match( candidate )
117
+ next unless seasons.include?( Season.parse( m[:season] ))
118
+ else
119
+ next ## note - no season found in filename; skip too
120
+ end
121
+ end
122
+
113
123
 
124
+ ## (ii) check for (default/built-in) ignore/excludes
125
+ basename = File.basename( candidate, File.extname( candidate ))
126
+ dirname = File.dirname( candidate )
114
127
 
115
- #########
116
- ### exclude squad
117
- ## and .v2 or .v2603
128
+ ### exclude basenames with:
129
+ ## - squad
130
+ ## - .v2 or .v2603
118
131
  ##
119
132
  ## - worldcup/more/1930_squads.txt => squads
120
- ## - 2014--brazil/cup.v2.txt",
121
- ## - 2014--brazil/cup.v260318_164934.txt",
122
-
123
- basename = File.basename( candidate, File.extname( candidate ))
133
+ ## - 2014--brazil/cup.v2.txt
134
+ ## - 2014--brazil/cup.v260318_164934.txt
124
135
 
125
- next if /squad/i.match( basename )
126
- next if /\.v[0-9][0-9_]*/i.match( basename )
136
+ next if /squad/i.match?( basename )
137
+ next if /\.v[0-9][0-9_]*/i.match?( basename )
127
138
 
128
139
  #####
129
- ### exclude dirs w/ squad or wiki
130
- dirname = File.dirname( candidate )
131
-
132
- next if /squad|wiki/i.match( dirname )
140
+ ### exclude dirs with:
141
+ ## - squad or wiki
142
+ next if /squad|wiki/i.match?( dirname )
133
143
 
134
144
 
135
145
  datafiles << candidate
136
- end
137
146
  end
138
147
 
139
148
  ## pp datafiles
@@ -143,13 +152,19 @@ end
143
152
 
144
153
 
145
154
 
146
-
155
+ ##
156
+ ## rename/change to read_csv - why? why not?
147
157
  def self.read( src )
148
- recs = read_csv( src )
158
+ ## note: normalize scr - use File.expand_path ??
159
+ ## change all backslash to slash for now
160
+ ## scr = scr.gsub( "\\", '/' )
161
+ fullsrc = File.expand_path( scr )
162
+
163
+ recs = read_csv( fullsrc )
149
164
  pp recs if debug?
150
165
 
151
166
  ## note - make pathspecs relative to passed in file arg!!!
152
- basedir = File.dirname( src )
167
+ basedir = File.dirname( fullsrc )
153
168
 
154
169
  recs.each do |rec|
155
170
  path = rec['path']
@@ -165,90 +180,69 @@ end
165
180
 
166
181
 
167
182
 
183
+ def self.build( args, filepack: nil )
184
+ recs = []
168
185
 
169
- end # class Pathspec
170
-
171
-
172
-
173
- ##
174
- # PathspecReport (aka/formerly BatchReport)
186
+ ## check fo no args case (and filepack present with default)
187
+ if args.empty?
188
+ if filepack && filepack.has_key?('default')
189
+ recs << { 'path' => '<default>',
190
+ 'datafiles' => filepack['default'] }
191
+ end
192
+ else
193
+
194
+ ## note - collect all "loose/standalone" files (NOT directories)
195
+ ## in single default pathspec node
196
+ more = []
197
+
198
+
199
+ args.each do |arg|
200
+ if filepack && filepack.has_key?( arg.downcase )
201
+ recs << { 'path' => "<#{arg.downcase}>",
202
+ 'datafiles' => filepack[arg.downcase] }
203
+ ## check if directory
204
+ elsif Dir.exist?( arg )
205
+ recs << { 'path' => arg,
206
+ 'datafiles' => _find( arg ) }
207
+ elsif File.file?( arg ) ## assume it's a file
208
+ ## make sure path exists; raise error if not
209
+ ## (auto-)expand path to normalize - yes why? why not?
210
+ more << File.expand_path( arg )
211
+ else
212
+ raise Errno::ENOENT, "No such file or directory - #{arg}"
213
+ end
214
+ end
175
215
 
176
- class PathspecReport
177
- def initialize( specs, title: )
178
- @specs = specs
179
- @title = title
216
+ if more.size > 0
217
+ recs << { 'path' => '<input>',
218
+ 'datafiles' => more }
219
+ end
180
220
  end
181
221
 
182
- def build
183
- buf = String.new
184
- buf << "# #{@title} - #{@specs.size} dataset(s)\n\n"
185
-
186
- @specs.each_with_index do |rec,i|
187
- datafiles = rec['datafiles']
188
- errors = rec['errors']
189
-
190
- if errors.size > 0
191
- buf << "!! #{errors.size} ERROR(S) "
192
- else
193
- buf << " OK "
194
- end
195
- buf << "%-20s" % rec['path']
196
- buf << " - #{datafiles.size} datafile(s)"
197
- buf << "\n"
198
-
199
- if errors.size > 0
200
- buf << errors.pretty_inspect
201
- buf << "\n"
202
- end
203
- end
204
-
205
- buf
206
- end # method build
207
- end # class BatchReport
208
-
209
- BatchReport = PathspecReport
222
+ recs
223
+ end
210
224
 
225
+ end # class Pathspec
211
226
  end # module Sportdb
212
227
 
213
228
 
214
229
 
230
+
215
231
  ##
216
232
  ## keep helpers as global functions - why? why not?
217
233
 
218
234
 
219
-
220
- def build_pathspecs( args ) ### note: was expand_args
221
- specs = []
222
-
223
- ## note - collect all "loose/standalone" files (NOT directories)
224
- ## in single default pathspec node
225
- more = []
226
-
227
- args.each do |arg|
228
- ## check if directory
229
- if Dir.exist?( arg )
230
- datafiles = SportDb::Pathspec._find( arg )
231
- specs << { 'path' => arg,
232
- 'datafiles' => datafiles }
233
- elsif File.file?( arg ) ## assume it's a file
234
- ## make sure path exists; raise error if not
235
- ## (auto-)expand path to normalize - why? why not?
236
- more << arg
237
- else
238
- raise Errno::ENOENT, "No such file or directory - #{arg}"
239
- end
240
- end
241
-
242
- if more.size > 0
243
- specs << { 'path' => '<input>',
244
- 'datafiles' => more }
245
- end
246
-
247
- specs
235
+ ## build pathspecs via arguments
236
+ ## - (i) every dir is a pathspec entry/record
237
+ ## - (ii) all files get bundled together into <input> pathspec entry/record
238
+ ##
239
+ ## note: was formerly known as expand_args
240
+ def build_pathspecs( args, filepack: nil )
241
+ SportDb::Pathspec.build( args, filepack: filepack )
248
242
  end
249
243
 
250
-
251
-
244
+ ####
245
+ ## read pathspecs via csv file (using path column)
252
246
  def read_pathspecs( src )
253
247
  SportDb::Pathspec.read( src )
254
248
  end
@@ -0,0 +1,42 @@
1
+ module SportDb
2
+
3
+ ##
4
+ # PathspecReport (aka/formerly BatchReport)
5
+
6
+ class PathspecReport
7
+ def initialize( specs, title: )
8
+ @specs = specs
9
+ @title = title
10
+ end
11
+
12
+ def build
13
+ buf = String.new
14
+ buf << "# #{@title} - #{@specs.size} dataset(s)\n\n"
15
+
16
+ @specs.each_with_index do |rec,i|
17
+ datafiles = rec['datafiles']
18
+ errors = rec['errors']
19
+
20
+ if errors.size > 0
21
+ buf << "!! #{errors.size} ERROR(S) "
22
+ else
23
+ buf << " OK "
24
+ end
25
+ buf << "%-20s" % rec['path']
26
+ buf << " - #{datafiles.size} datafile(s)"
27
+ buf << "\n"
28
+
29
+ if errors.size > 0
30
+ buf << errors.pretty_inspect
31
+ buf << "\n"
32
+ end
33
+ end
34
+
35
+ buf
36
+ end # method build
37
+ end # class BatchReport
38
+
39
+ BatchReport = PathspecReport
40
+
41
+
42
+ end # module Sportdb
data/lib/fbtok.rb CHANGED
@@ -3,8 +3,9 @@ require 'sportdb/quick'
3
3
 
4
4
 
5
5
  ## our own code
6
+ require_relative 'fbtok/filepack'
6
7
  require_relative 'fbtok/pathspec'
7
-
8
+ require_relative 'fbtok/pathspec_report'
8
9
 
9
10
  require_relative 'fbtok/fbtok'
10
11
  require_relative 'fbtok/fbtree'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fbtok
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-05-31 00:00:00.000000000 Z
11
+ date: 2026-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sportdb-parser
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.7.1
19
+ version: 0.7.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.7.1
26
+ version: 0.7.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: sportdb-quick
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -100,7 +100,9 @@ files:
100
100
  - lib/fbtok/fbtok.rb
101
101
  - lib/fbtok/fbtree.rb
102
102
  - lib/fbtok/fbx.rb
103
+ - lib/fbtok/filepack.rb
103
104
  - lib/fbtok/pathspec.rb
105
+ - lib/fbtok/pathspec_report.rb
104
106
  homepage: https://github.com/sportdb/footty
105
107
  licenses:
106
108
  - Public Domain