fbtok 0.3.4 → 0.4.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 +4 -4
- data/CHANGELOG.md +1 -1
- data/Manifest.txt +2 -4
- data/README.md +55 -8
- data/Rakefile +3 -5
- data/bin/{fbt → fbquick} +25 -34
- data/bin/fbtok +29 -40
- data/bin/fbtree +26 -32
- data/bin/fbx +16 -59
- data/lib/fbtok/pathspec.rb +230 -0
- data/lib/fbtok.rb +2 -9
- metadata +10 -13
- data/bin/fbchk +0 -158
- data/lib/fbtok/linter.rb +0 -119
- data/lib/fbtok/opts.rb +0 -195
data/lib/fbtok/opts.rb
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module SportDb
|
|
3
|
-
class Parser
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
###
|
|
7
|
-
## note - Opts Helpers for now nested inside Parser - keep here? why? why not?
|
|
8
|
-
class Opts
|
|
9
|
-
|
|
10
|
-
def self.debug=(value) @@debug = value; end
|
|
11
|
-
def self.debug?() @@debug ||= false; end ## note: default is FALSE
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
SEASON_RE = %r{ (?:
|
|
15
|
-
(?<season>\d{4}-\d{2})
|
|
16
|
-
|
|
|
17
|
-
(?<season>\d{4})
|
|
18
|
-
(?: --[a-z0-9_-]+ )? ## todo/fix - allow "extension" to 2024-25 too - why?
|
|
19
|
-
)
|
|
20
|
-
}x
|
|
21
|
-
SEASON = SEASON_RE.source ## "inline" helper for embedding in other regexes - keep? why? why not?
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
## note: if pattern includes directory add here
|
|
25
|
-
## (otherwise move to more "generic" datafile) - why? why not?
|
|
26
|
-
## update - note include/allow dot (.) too
|
|
27
|
-
## BUT NOT as first character!!! (e.g. exclude .confg.txt !!!)
|
|
28
|
-
## e.g. 2024-25/at.1.txt
|
|
29
|
-
## change to at_1 or uefa_cl or such - why? why not?
|
|
30
|
-
MATCH_RE = %r{ (?: ## "classic" variant i) with season folder
|
|
31
|
-
(?: ^|/ ) # beginning (^) or beginning of path (/)
|
|
32
|
-
#{SEASON}
|
|
33
|
-
/
|
|
34
|
-
[a-z0-9][a-z0-9_.-]*\.txt$ ## txt e.g /1-premierleague.txt
|
|
35
|
-
)
|
|
36
|
-
|
|
|
37
|
-
(?: ## "compact" variant ii) with season in filename
|
|
38
|
-
(?: ^|/ ) # beginning (^) or beginning of path (/)
|
|
39
|
-
(?: (?<season>\d{4}-\d{2})
|
|
40
|
-
|
|
|
41
|
-
(?<season>\d{4})
|
|
42
|
-
)
|
|
43
|
-
_ ## allow more than one underscore - why? why not?
|
|
44
|
-
[a-z0-9][a-z0-9_.-]*\.txt$
|
|
45
|
-
)
|
|
46
|
-
}x
|
|
47
|
-
|
|
48
|
-
### add support for matchdatafile with season NOT in directory
|
|
49
|
-
## but starting filename e.g. 2024_friendlies.txt or 2024-25_bundesliga.txt
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def self._find( path, seasons: nil )
|
|
53
|
-
## check - rename dir
|
|
54
|
-
## use root_dir or work_dir or cd or such - why? why not?
|
|
55
|
-
|
|
56
|
-
datafiles = []
|
|
57
|
-
|
|
58
|
-
## note: normalize path - use File.expand_path ??
|
|
59
|
-
## change all backslash to slash for now
|
|
60
|
-
## path = path.gsub( "\\", '/' )
|
|
61
|
-
path = File.expand_path( path )
|
|
62
|
-
|
|
63
|
-
if seasons && seasons.size > 0
|
|
64
|
-
## norm seasons
|
|
65
|
-
seasons = seasons.map {|season| Season(season) }
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
## check all txt files
|
|
70
|
-
## note: incl. files starting with dot (.)) as candidates
|
|
71
|
-
## (normally excluded with just *)
|
|
72
|
-
candidates = Dir.glob( "#{path}/**/{*,.*}.txt" )
|
|
73
|
-
## pp candidates
|
|
74
|
-
candidates.each do |candidate|
|
|
75
|
-
if m=MATCH_RE.match( candidate )
|
|
76
|
-
if seasons && seasons.size > 0 ## check for seasons filter
|
|
77
|
-
season = Season.parse(m[:season])
|
|
78
|
-
datafiles << candidate if seasons.include?( season )
|
|
79
|
-
else
|
|
80
|
-
datafiles << candidate
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
## pp datafiles
|
|
86
|
-
datafiles
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def self._expand( arg )
|
|
91
|
-
## check if directory
|
|
92
|
-
if Dir.exist?( arg )
|
|
93
|
-
datafiles = _find( arg )
|
|
94
|
-
if debug?
|
|
95
|
-
puts
|
|
96
|
-
puts " found #{datafiles.size} match txt datafiles in #{arg}"
|
|
97
|
-
pp datafiles
|
|
98
|
-
end
|
|
99
|
-
datafiles
|
|
100
|
-
else ## assume it's a file
|
|
101
|
-
## make sure path exists; raise error if not
|
|
102
|
-
if File.exist?( arg )
|
|
103
|
-
[arg] ## note - always return an array - why? why not?
|
|
104
|
-
else
|
|
105
|
-
raise Errno::ENOENT, "No such file or directory - #{arg}"
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
def self.expand_args( args )
|
|
112
|
-
paths = []
|
|
113
|
-
args.each do |arg|
|
|
114
|
-
paths += _expand( arg )
|
|
115
|
-
end
|
|
116
|
-
paths
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
## todo/check - find a better name
|
|
122
|
-
## e.g. BatchItem or PackageDef or ???
|
|
123
|
-
##
|
|
124
|
-
## find a different name for rec for named value props?
|
|
125
|
-
## why? why not?
|
|
126
|
-
PathspecNode = Struct.new( :paths, :rec )
|
|
127
|
-
|
|
128
|
-
def self.build_pathspec( paths: )
|
|
129
|
-
PathspecNode.new( paths: paths, rec: {} )
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def self.read_pathspecs( src )
|
|
133
|
-
specs = []
|
|
134
|
-
|
|
135
|
-
recs = read_csv( src )
|
|
136
|
-
pp recs if debug?
|
|
137
|
-
|
|
138
|
-
## note - make pathspecs relative to passed in file arg!!!
|
|
139
|
-
basedir = File.dirname( src )
|
|
140
|
-
recs.each do |rec|
|
|
141
|
-
path = rec['path']
|
|
142
|
-
fullpath = File.expand_path( path, basedir )
|
|
143
|
-
## make sure path exists; raise error if not
|
|
144
|
-
paths = if Dir.exist?( fullpath )
|
|
145
|
-
_find( fullpath )
|
|
146
|
-
else
|
|
147
|
-
raise Errno::ENOENT, "No such directory - #{fullpath})"
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
specs << PathspecNode.new( paths: paths, rec: rec )
|
|
151
|
-
end
|
|
152
|
-
specs
|
|
153
|
-
end
|
|
154
|
-
end # class Opts
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
##
|
|
158
|
-
# BatchReport (a.k.a. PathspecsReport)
|
|
159
|
-
|
|
160
|
-
class BatchReport
|
|
161
|
-
|
|
162
|
-
def initialize( specs, title: )
|
|
163
|
-
@specs = specs
|
|
164
|
-
@title = title
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
def build
|
|
168
|
-
buf = String.new
|
|
169
|
-
buf << "# #{@title} - #{@specs.size} dataset(s)\n\n"
|
|
170
|
-
|
|
171
|
-
@specs.each_with_index do |spec,i|
|
|
172
|
-
paths = spec.paths
|
|
173
|
-
rec = spec.rec
|
|
174
|
-
errors = rec['errors']
|
|
175
|
-
|
|
176
|
-
if errors.size > 0
|
|
177
|
-
buf << "!! #{errors.size} ERROR(S) "
|
|
178
|
-
else
|
|
179
|
-
buf << " OK "
|
|
180
|
-
end
|
|
181
|
-
buf << "%-20s" % rec['path']
|
|
182
|
-
buf << " - #{paths.size} datafile(s)"
|
|
183
|
-
buf << "\n"
|
|
184
|
-
|
|
185
|
-
if errors.size > 0
|
|
186
|
-
buf << errors.pretty_inspect
|
|
187
|
-
buf << "\n"
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
buf
|
|
192
|
-
end # method build
|
|
193
|
-
end # class BatchReport
|
|
194
|
-
end # class Parser
|
|
195
|
-
end # module SportDb
|