Skip to content

Commit a9d3350

Browse files
committed
style: standardrb clean across lib (URI.parse().open, ranges, struct, access modifiers)
The ml files merged in #805 had never been linted (rake.yml was red, so StandardRB never gated them). Autofixes + manual conversions; no behavior change — imf/provisioning URI fetches keep their open-uri requires.
1 parent b49fcf1 commit a9d3350

7 files changed

Lines changed: 71 additions & 71 deletions

File tree

‎lib/interscript/ml/imf.rb‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def encode(text)
3232
# corpora emit '/'-separated alternates per token; the runtime
3333
# returns the primary choice only.
3434
def first_alternates(text)
35-
text.split.map { |tok| tok.split('/', 2).first }.join(' ')
35+
text.split.map { |tok| tok.split("/", 2).first }.join(" ")
3636
end
3737

3838
def decode(token_ids)
@@ -112,7 +112,7 @@ def resolve(model_id, index_url: nil)
112112
if channel.start_with?("file://")
113113
FileUtils.cp(channel.sub(%r{\Afile://}, ""), tmp)
114114
else
115-
URI.open(channel) { |remote| IO.copy_stream(remote, tmp) }
115+
URI.parse(channel).open { |remote| IO.copy_stream(remote, tmp) }
116116
end
117117
end
118118
actual = Digest::SHA256.file(tmp).hexdigest
@@ -140,14 +140,14 @@ def download_parts(entry, tmp)
140140
if part["url"].start_with?("file://")
141141
File.open(source, "rb", &open_stream)
142142
else
143-
URI.open(source, "rb", &open_stream)
143+
URI.parse(source).open("rb", &open_stream)
144144
end
145145
unless digest.hexdigest == part["sha256"]
146146
raise RegistryError, "part #{index} of #{entry["filename"]} sha256 mismatch: got #{digest.hexdigest}, index says #{part["sha256"]}"
147147
end
148148
end
149149
end
150-
rescue StandardError
150+
rescue
151151
File.delete(tmp) if File.file?(tmp)
152152
raise
153153
end
@@ -167,10 +167,10 @@ def load_index(source)
167167
# HTTP sources must ship a sibling .sha256 sidecar; verify the
168168
# body against it before parsing (GitHub Releases index assets do).
169169
def fetch_index_with_sidecar(source)
170-
body = URI.open(source, "rb") { |remote| remote.read }
170+
body = URI.parse(source).open("rb") { |remote| remote.read }
171171
sidecar =
172172
begin
173-
URI.open("#{source}.sha256") { |remote| remote.read }
173+
URI.parse("#{source}.sha256").open { |remote| remote.read }
174174
rescue OpenURI::HTTPError => e
175175
raise RegistryError, "index sha256 sidecar missing: #{source}.sha256 (#{e.message})"
176176
end

‎lib/interscript/ml/model.rb‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,30 @@ class Model
55
def self.from_file(model_file)
66
# A models.yaml model id resolves (download -> verify -> cache)
77
# through the same contract as the Python/TS runtimes.
8-
model_file = IMF.resolve(model_file) unless model_file.to_s.end_with?('.zip') || File.file?(model_file.to_s)
8+
model_file = IMF.resolve(model_file) unless model_file.to_s.end_with?(".zip") || File.file?(model_file.to_s)
99
model_file = Provisioning.locate(model_file)
1010

1111
Zip::File.open(model_file) do |zip_file|
12-
metadata = zip_file.glob('metadata.yaml').first
12+
metadata = zip_file.glob("metadata.yaml").first
1313
metadata = YAML.safe_load(metadata.get_input_stream.read) if metadata
1414

1515
# IMF v1: the Interscript Model Format zip.
16-
return Byt5Onnx.new(model_file) if metadata && metadata['format'] == 'imf-v1'
16+
return Byt5Onnx.new(model_file) if metadata && metadata["format"] == "imf-v1"
1717

18-
name = metadata && metadata['name']
18+
name = metadata && metadata["name"]
1919

2020
# Modern byte-level seq2seq (ByT5 family): encoder.onnx + decoder.onnx.
21-
return Byt5Onnx.new(model_file) if name == 'byt5'
21+
return Byt5Onnx.new(model_file) if name == "byt5"
2222

2323
# Legacy single-file ONNX transformer zips (vocabs.yaml based).
24-
vocabs = zip_file.glob('vocabs.yaml').first
25-
raise 'vocabs.yaml is missing in model zip!' unless vocabs
24+
vocabs = zip_file.glob("vocabs.yaml").first
25+
raise "vocabs.yaml is missing in model zip!" unless vocabs
2626
vocabs = YAML.safe_load(vocabs.get_input_stream.read)
27-
input_vocab = Vocab.new(vocabs['input'], specials: [])
28-
target_vocab = Vocab.new(vocabs['target'], specials: [])
27+
input_vocab = Vocab.new(vocabs["input"], specials: [])
28+
target_vocab = Vocab.new(vocabs["target"], specials: [])
2929

30-
onnx = zip_file.glob('*.onnx').first
31-
raise 'onnx model file is missing in model zip!' unless onnx
30+
onnx = zip_file.glob("*.onnx").first
31+
raise "onnx model file is missing in model zip!" unless onnx
3232
Onnx.new(onnx.get_input_stream.read, input_vocab, target_vocab)
3333
end
3434
end
@@ -41,11 +41,11 @@ def initialize(model_path_or_bytes, input_vocab, target_vocab)
4141
end
4242

4343
def call(input, output, opts)
44-
@model.predict({ src: input, tgt: output }.merge(opts))['output']
44+
@model.predict({src: input, tgt: output}.merge(opts))["output"]
4545
end
4646

4747
def argmax(*args)
48-
self.call(*args).map { |i| i.flatten.each_with_index.max[1] }
48+
call(*args).map { |i| i.flatten.each_with_index.max[1] }
4949
end
5050
end
5151
end

‎lib/interscript/ml/plane.rb‎

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

3-
require 'tmpdir'
4-
require 'json'
3+
require "tmpdir"
4+
require "json"
55

66
module Interscript
77
module ML
@@ -16,7 +16,7 @@ class PlaneModel
1616
attr_reader :classes, :k_passes
1717

1818
def initialize(graph:, classes:, k_passes: 2)
19-
Interscript::ML.require_optional!('onnxruntime')
19+
Interscript::ML.require_optional!("onnxruntime")
2020
@classes = classes.freeze
2121
@n_classes = classes.length
2222
@mask_id = @n_classes
@@ -27,8 +27,8 @@ def initialize(graph:, classes:, k_passes: 2)
2727
@class_to_id = classes.each_with_index.to_h.freeze
2828
# the onnxruntime gem loads from paths, not bytes (as byt5_onnx):
2929
# verified bytes go to a tmpfile owned by this instance
30-
@graph_tmpdir = Dir.mktmpdir('isx-plane')
31-
path = File.join(@graph_tmpdir, 'plane.onnx')
30+
@graph_tmpdir = Dir.mktmpdir("isx-plane")
31+
path = File.join(@graph_tmpdir, "plane.onnx")
3232
File.binwrite(path, graph)
3333
@sess = OnnxRuntime::Model.new(path)
3434
end
@@ -58,7 +58,7 @@ def split_planes(text)
5858
else
5959
close.call
6060
skeleton << ch
61-
classes << ''
61+
classes << ""
6262
end
6363
end
6464
close.call
@@ -75,18 +75,18 @@ def translate(text, preserve_diacritics: false)
7575
ch = skeleton[i]
7676
n = ch.bytesize
7777
cls = if user_cls.empty?
78-
votes = tok_preds[pos, n] || []
79-
cid = votes.tally.max_by { |_, c| c }&.first || @n_classes
80-
cid < @n_classes ? @classes[cid] : ''
81-
else
82-
user_cls # user diacritics round-trip byte-exactly
83-
end
78+
votes = tok_preds[pos, n] || []
79+
cid = votes.tally.max_by { |_, c| c }&.first || @n_classes
80+
(cid < @n_classes) ? @classes[cid] : ""
81+
else
82+
user_cls # user diacritics round-trip byte-exactly
83+
end
8484
pos += n
8585
cls
8686
end
8787
out = +""
8888
skeleton.each_char.with_index do |ch, i|
89-
out << (ch == "\x00" ? final[i] : ch + final[i])
89+
out << ((ch == "\x00") ? final[i] : ch + final[i])
9090
end
9191
out
9292
end
@@ -102,7 +102,7 @@ def translate_plain(text)
102102
votes = preds[pos, nbytes] || []
103103
cid = votes.tally.max_by { |_, c| c }&.first || @n_classes
104104
pos += nbytes
105-
cid < @n_classes ? @classes[cid] : ''
105+
(cid < @n_classes) ? @classes[cid] : ""
106106
end
107107
PlaneModel.render_plane(text, char_preds)
108108
end
@@ -111,7 +111,7 @@ def k_pass_decode(ids, plane0)
111111
plane = plane0
112112
preds = nil
113113
@k_passes.times do
114-
logits = @sess.predict({ 'input_ids' => [ids], 'plane_ids' => [plane] })['class_logits'][0]
114+
logits = @sess.predict({"input_ids" => [ids], "plane_ids" => [plane]})["class_logits"][0]
115115
preds = logits.each_with_index.map { |row, i| row.index(row.max) }
116116
plane = preds
117117
end
@@ -129,11 +129,11 @@ def decode_pinned(skeleton, char_classes)
129129
pid = @class_to_id.fetch(cls, @mask_id)
130130
ch.bytesize.times { per_token_pin << pid }
131131
end
132-
plane0 = per_token_pin.map { |p| p == @mask_id ? @mask_id : p }
132+
plane0 = per_token_pin.map { |p| (p == @mask_id) ? @mask_id : p }
133133
k_pass_decode(ids, plane0)
134134
end
135135

136-
def self.render_plane(skeleton, char_classes)
136+
def self.render_plane(skeleton, char_classes) # rubocop:disable Lint/IneffectiveAccessModifier
137137
skeleton.each_char.with_index.map do |ch, i|
138138
ch + char_classes[i].to_s
139139
end.join
@@ -142,14 +142,15 @@ def self.render_plane(skeleton, char_classes)
142142
# The zip contract: metadata.yaml (kind=plane, k_passes, member
143143
# sha256s) + plane.onnx + classes.json, every member sha-verified
144144
# before the session is created.
145+
# rubocop:disable Lint/IneffectiveAccessModifier
145146
def self.from_zip(data)
146-
require 'zip'
147+
require "zip"
147148
zf = Zip::File.open_buffer(data)
148149
names = zf.entries.map(&:name)
149-
meta = YAML.safe_load(zf.read('metadata.yaml'), permitted_classes: [], aliases: false)
150-
raise IMF::FormatError, "plane zip: kind=#{meta['kind'].inspect}, expected 'plane'" if meta['kind'] != 'plane'
150+
meta = YAML.safe_load(zf.read("metadata.yaml"), permitted_classes: [], aliases: false)
151+
raise IMF::FormatError, "plane zip: kind=#{meta["kind"].inspect}, expected 'plane'" if meta["kind"] != "plane"
151152

152-
members = meta['members'] || {}
153+
members = meta["members"] || {}
153154
plane_graph = nil
154155
classes_bytes = nil
155156
%w[plane.onnx classes.json].each do |member|
@@ -161,18 +162,20 @@ def self.from_zip(data)
161162
got = Digest::SHA256.hexdigest(bytes)
162163
raise IMF::FormatError, "plane zip: #{member} sha256 mismatch (#{got})" if want != got
163164

164-
plane_graph = bytes if member == 'plane.onnx'
165-
classes_bytes = bytes if member == 'classes.json'
165+
plane_graph = bytes if member == "plane.onnx"
166+
classes_bytes = bytes if member == "classes.json"
166167
end
167168
classes = JSON.parse(classes_bytes)
168-
new(graph: plane_graph, classes: classes, k_passes: meta.fetch('k_passes', 2))
169+
new(graph: plane_graph, classes: classes, k_passes: meta.fetch("k_passes", 2))
169170
ensure
170171
zf&.close
171172
end
172173
end
173174

174175
module_function
175176

177+
# rubocop:enable Lint/IneffectiveAccessModifier
178+
176179
def render_plane(skeleton, char_classes)
177180
PlaneModel.render_plane(skeleton, char_classes)
178181
end

‎lib/interscript/ml/provisioning.rb‎

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
require 'open-uri'
2-
require 'uri'
3-
require 'fileutils'
4-
require 'digest/sha2'
5-
require 'yaml'
1+
require "open-uri"
2+
require "uri"
3+
require "fileutils"
4+
require "digest/sha2"
5+
require "yaml"
66

77
module Interscript::ML
88
# Module Interscript::ML::Provisioning is to provision remote models locally and to
@@ -37,7 +37,7 @@ def prepare_environment
3737

3838
([ENV["INTERSCRIPT_ML_DATA"] || ENV["SECRYST_DATA"]] + possible_paths).compact.each do |path|
3939
FileUtils.mkdir_p(path)
40-
@write_path = path unless @write_path
40+
@write_path ||= path
4141
rescue
4242
ensure
4343
@read_paths << path if File.readable?(path)
@@ -48,11 +48,11 @@ def prepare_environment
4848
# Now, let's locate the first Secrystfile to be found
4949
path = Dir.pwd
5050
secrystfilepath = loop do
51-
break unless path =~ %r{[/\\]}
51+
break unless %r{[/\\]}.match?(path)
5252
if File.readable?(path + "/Secrystfile")
5353
break path + "/Secrystfile"
5454
end
55-
path = path.sub(%r{[/\\][^/\\]*?\z}, '')
55+
path = path.sub(%r{[/\\][^/\\]*?\z}, "")
5656
end
5757

5858
# It's found, so let's parse it.
@@ -70,12 +70,12 @@ def prepare_environment
7070
@loaded_remotes = @remotes.map do |uri|
7171
cache_path = "#{@write_path}/remotes/#{Digest::SHA256.hexdigest(uri)}.yaml"
7272
if !File.exist?(cache_path)
73-
data = URI.open(uri).read
73+
data = URI.parse(uri).open.read
7474
File.write(cache_path, data)
7575
elsif File.mtime(cache_path) + 60 < Time.now
7676
begin
7777
# Just *try* to download it.
78-
data = URI.open(uri).read
78+
data = URI.parse(uri).open.read
7979
File.write(cache_path, data)
8080
rescue
8181
end
@@ -99,7 +99,7 @@ def self.candidate_paths
9999

100100
def locate(name)
101101
# Shortcut this if user gave a filename.
102-
return name if name =~ %r{[.\\/]}
102+
return name if %r{[.\\/]}.match?(name)
103103

104104
prepare_environment
105105

@@ -130,24 +130,24 @@ def locate(name)
130130

131131
def download(model, remote:)
132132
uri = model.uri
133-
if uri.start_with?("./") || uri.start_with?("../")
133+
if uri.start_with?("./", "../")
134134
remote_uri = remote.uri
135-
if remote_uri =~ %r{\A/|\A\w:[\\/]}
136-
remote_uri = "file://"+remote_uri
135+
if %r{\A/|\A\w:[\\/]}.match?(remote_uri)
136+
remote_uri = "file://" + remote_uri
137137
end
138138

139139
uri = URI(remote_uri).merge(uri).to_s
140-
uri = uri.sub(%r{\Afile://}, '')
140+
uri = uri.sub(%r{\Afile://}, "")
141141
end
142142

143143
warn "* Downloading a Secryst model #{model.name}:#{model.version} from #{uri}..."
144144

145-
data = URI.open(uri).read
145+
data = URI.parse(uri).open.read
146146
path = @write_path + "/models/" + model.name
147147
FileUtils.mkdir_p path
148148
File.write(path + "/version", model.version)
149149
File.write(path + "/model.zip", data)
150-
return path + "/model.zip"
150+
path + "/model.zip"
151151
end
152152

153153
class Remotefile
@@ -166,15 +166,15 @@ def resolve(name)
166166
end
167167
end
168168

169-
class Model < Struct.new(:name, :uri, :version, keyword_init: true)
169+
class Model < Struct.new(:name, :uri, :version)
170170
end
171171
end
172172

173173
class Secrystfile
174174
def initialize(path)
175175
@path = path
176176
@models, @remotes = [], []
177-
self.instance_eval(File.read(path), path)
177+
instance_eval(File.read(path), path)
178178
end
179179

180180
def model(name)

‎lib/interscript/ml/translator.rb‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ class Translator
66
attr_accessor :model
77

88
def initialize(model_file:)
9-
@device = 'cpu'
9+
@device = "cpu"
1010
@model = Model.from_file(model_file)
1111
end
1212

1313
def translate(phrase, max_seq_length: 100)
1414
return @model.translate(phrase, max_seq_length: max_seq_length) if @model.is_a?(Byt5Onnx)
1515

1616
Interscript::ML.require_optional!("numo-narray", feature: "numo/narray")
17-
input = ['<sos>'] + phrase.chars + ['<eos>']
17+
input = ["<sos>"] + phrase.chars + ["<eos>"]
1818
input = Numo::NArray[input.map { |i| @model.input_vocab.stoi[i] }].transpose
19-
output = Numo::NArray[[@model.target_vocab.stoi['<sos>']]]
19+
output = Numo::NArray[[@model.target_vocab.stoi["<sos>"]]]
2020
src_key_padding_mask = input.transpose.eq(1)
2121

2222
max_seq_length.times do |i|
@@ -27,12 +27,12 @@ def translate(phrase, max_seq_length: 100)
2727
src_key_padding_mask: src_key_padding_mask,
2828
tgt_key_padding_mask: tgt_key_padding_mask,
2929
memory_key_padding_mask: src_key_padding_mask)
30-
break if @model.target_vocab.itos[prediction[i]] == '<eos>'
30+
break if @model.target_vocab.itos[prediction[i]] == "<eos>"
3131

3232
output = Numo::NArray.concatenate([output, Numo::NArray[[prediction[i]]]])
3333
end
3434

35-
output[1..-1].to_a.flatten.map { |i| @model.target_vocab.itos[i] }.join('')
35+
output[1..].to_a.flatten.map { |i| @model.target_vocab.itos[i] }.join("")
3636
end
3737
end
3838
end

0 commit comments

Comments
 (0)