zlight_csv 0.4.0-aarch64-linux → 0.6.0-aarch64-linux

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.
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ZLight
4
+ # Loads the compiled extension.
5
+ #
6
+ # A precompiled gem ships one shared library per Ruby minor version, laid out
7
+ # as lib/zlight_csv/<major.minor>/zlight_csv.<so|bundle|dll>, because a C
8
+ # extension built against one Ruby's ABI cannot be loaded by another. A gem
9
+ # built from source has a single library at lib/zlight_csv instead, so try
10
+ # the versioned path first and fall back.
11
+ module Native
12
+ def self.load!
13
+ require_relative "#{RUBY_VERSION[/\d+\.\d+/]}/zlight_csv"
14
+ rescue LoadError
15
+ require_relative 'zlight_csv'
16
+ end
17
+ end
18
+ end
19
+
20
+ ZLight::Native.load!
data/lib/zlight_csv.rb CHANGED
@@ -1,304 +1,183 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'zlight_csv/version'
4
+ require_relative 'zlight_csv/errors'
5
+ require_relative 'zlight_csv/native'
4
6
 
5
- # Load the prebuilt native extension for this Ruby version
6
- begin
7
- ruby_version = RUBY_VERSION.match(/(\d+\.\d+)/)[1]
8
- require_relative "zlight_csv/#{ruby_version}/zlight_csv"
9
- rescue LoadError
10
- require_relative 'zlight_csv/zlight_csv'
11
- end
12
-
13
- # ZLight is a high-performance CSV parser for Ruby, powered by Rust.
14
- #
15
- # It provides a simple, Ruby CSV-compatible API for parsing CSV files
16
- # up to 30x faster than the standard library.
17
- #
18
- # @example Basic parsing with headers
19
- # result = ZLight.parse("name,age\nAlice,30\nBob,25")
20
- # # => [{:name=>"Alice", :age=>"30"}, {:name=>"Bob", :age=>"25"}]
7
+ # ZLight is a CSV parser and writer for Ruby, implemented in Rust.
21
8
  #
22
- # @example Parsing with numeric conversion
23
- # result = ZLight.parse("name,age\nAlice,30", converters: :numeric)
24
- # # => [{:name=>"Alice", :age=>30}]
9
+ # The public API is deliberately small. Four of the methods below are defined
10
+ # in the native extension and four are defined here in Ruby as conveniences on
11
+ # top of them; which is which is noted on each.
25
12
  #
26
- # @example Parsing without headers
27
- # result = ZLight.parse("Alice,30\nBob,25", headers: false)
28
- # # => [["Alice", "30"], ["Bob", "25"]]
13
+ # @example Parse a string
14
+ # ZLight.parse("name,age\nAlice,30") # => [{name: "Alice", age: "30"}]
29
15
  #
30
- # @example Reading from a file
31
- # result = ZLight.read("path/to/file.csv", headers: true)
16
+ # @example Parse a file, converting numbers
17
+ # ZLight.read("users.csv", converters: :numeric)
32
18
  #
33
- # @example Streaming large files
34
- # ZLight.stream_file("large.csv") do |reader|
35
- # reader.each { |row| process(row) }
36
- # end
19
+ # @example Stream a large file in constant memory
20
+ # ZLight.open("huge.csv") { |reader| reader.each { |row| process(row) } }
37
21
  #
38
- # @example Lazy iteration with Enumerator
39
- # reader = ZLight.stream_file("large.csv")
40
- # reader.lazy.select { |row| row[:age] > 30 }.first(10)
41
- # reader.close
22
+ # @example Write a file
23
+ # ZLight.write("out.csv", [{ name: "Alice", age: 30 }])
42
24
  #
43
- # @see https://github.com/zaidanch/zlight
25
+ # @see https://github.com/codebyisaad/zlight
26
+ # @see file:README.md#differences-from-stdlib-csv Differences from stdlib CSV
44
27
  module ZLight
45
- # Base error class for all ZLight errors
46
- class Error < StandardError; end
47
-
48
- # Raised when CSV parsing fails due to malformed data
49
- class ParseError < Error; end
50
-
51
- # Raised when CSV contains invalid UTF-8 encoding
52
- class EncodingError < Error; end
53
-
54
- # Raised when attempting to use a closed stream reader
55
- class StreamClosedError < Error; end
56
-
57
- # Parses a CSV string and returns an array of rows.
58
- #
59
- # This method is implemented as a native Rust extension for maximum performance.
60
- #
61
- # @param csv_string [String] The CSV data to parse
62
- # @param headers [Boolean] Treat first row as headers (default: true)
63
- # @param converters [Symbol, nil] Set to :numeric for auto-conversion of integers/floats
64
- # @param col_sep [String] Column separator character (default: ",")
65
- # @param quote_char [String] Quote character for escaping (default: '"')
66
- # @param flexible [Boolean] Allow variable-length records (default: true)
67
- #
68
- # @return [Array<Hash>] When headers: true, returns array of Hashes with Symbol keys
69
- # @return [Array<Array>] When headers: false, returns array of Arrays
70
- #
71
- # @raise [ArgumentError] If options are invalid
72
- # @raise [ZLight::ParseError] If CSV data is malformed
73
- # @raise [ZLight::EncodingError] If headers contain invalid UTF-8
74
- #
75
- # @example Parse with headers (default)
76
- # ZLight.parse("name,age\nAlice,30")
77
- # # => [{:name=>"Alice", :age=>"30"}]
78
- #
79
- # @example Parse without headers
80
- # ZLight.parse("Alice,30", headers: false)
81
- # # => [["Alice", "30"]]
82
- #
83
- # @example Parse with numeric conversion
84
- # ZLight.parse("name,age\nAlice,30", converters: :numeric)
85
- # # => [{:name=>"Alice", :age=>30}]
86
- #
87
- # @example Parse TSV (tab-separated values)
88
- # ZLight.parse("name\tage\nAlice\t30", col_sep: "\t")
89
- # # => [{:name=>"Alice", :age=>"30"}]
90
- #
91
- # @note The parse method is defined in the Rust native extension.
92
- # See ext/zlight_csv/src/lib.rs for implementation.
93
-
94
- # Generates a CSV string from an array of rows.
95
- #
96
- # This method is implemented as a native Rust extension for maximum performance.
97
- #
98
- # @param rows [Array<Hash>, Array<Array>] The data to convert to CSV
99
- # @param headers [Boolean] Write header row for hash input (default: true)
100
- # @param col_sep [String] Column separator character (default: ",")
101
- # @param quote_char [String] Quote character for escaping (default: '"')
102
- # @param force_quotes [Boolean] Force quoting all fields (default: false)
103
- #
104
- # @return [String] The generated CSV string
105
- #
106
- # @raise [ArgumentError] If options are invalid or rows format is mixed
107
- #
108
- # @example Generate CSV from array of hashes
109
- # ZLight.generate([{name: "Alice", age: 30}, {name: "Bob", age: 25}])
110
- # # => "name,age\nAlice,30\nBob,25\n"
111
- #
112
- # @example Generate CSV from array of arrays (no headers)
113
- # ZLight.generate([["Alice", 30], ["Bob", 25]])
114
- # # => "Alice,30\nBob,25\n"
115
- #
116
- # @example Generate without headers
117
- # ZLight.generate([{name: "Alice"}], headers: false)
118
- # # => "Alice\n"
119
- #
120
- # @example Generate TSV
121
- # ZLight.generate([{a: 1, b: 2}], col_sep: "\t")
122
- # # => "a\tb\n1\t2\n"
123
- #
124
- # @note The generate method is defined in the Rust native extension.
125
- # See ext/zlight_csv/src/writer.rs for implementation.
28
+ class << self
29
+ # @!method parse(csv_string, headers: true, converters: nil, col_sep: ",", quote_char: "\"", flexible: true)
30
+ # Parses a CSV string into an Array of rows.
31
+ #
32
+ # Defined in the native extension; see ext/zlight_csv/src/read/eager.rs.
33
+ # Reads Ruby's string buffer directly without copying it.
34
+ #
35
+ # @param csv_string [String] the CSV data
36
+ # @param headers [Boolean] treat the first row as headers, returning
37
+ # Hashes with Symbol keys; when false, rows are Arrays
38
+ # @param converters [Symbol, nil] `:numeric` converts integers and floats
39
+ # @param col_sep [String] single-byte column separator
40
+ # @param quote_char [String] single-byte quote character
41
+ # @param flexible [Boolean] allow rows with differing field counts
42
+ # @return [Array<Hash>, Array<Array>] one element per row
43
+ # @raise [ZLight::ParseError] if the CSV is malformed
44
+ # @raise [ZLight::EncodingError] if a header is not valid UTF-8
45
+ # @raise [ArgumentError] if an option is invalid
126
46
 
127
- # StreamReader is defined in the Rust extension.
128
- # It provides lazy/streaming CSV parsing for large files.
129
- #
130
- # @see ZLight.stream
131
- # @see ZLight.stream_file
47
+ # @!method generate(rows, headers: true, col_sep: ",", quote_char: "\"", force_quotes: false)
48
+ # Builds a CSV string from an Array of rows.
49
+ #
50
+ # Defined in the native extension; see ext/zlight_csv/src/write/mod.rs.
51
+ # Accepts an Array of Hashes or an Array of Arrays, not a mix of both.
52
+ # For Hashes the column order comes from the keys of the first one.
53
+ #
54
+ # @param rows [Array<Hash>, Array<Array>] the rows to write
55
+ # @param headers [Boolean] emit a header row (Hash input only)
56
+ # @param col_sep [String] single-byte column separator
57
+ # @param quote_char [String] single-byte quote character
58
+ # @param force_quotes [Boolean] quote every field, not only those needing it
59
+ # @return [String] the generated CSV
60
+ # @raise [ArgumentError] if an option is invalid or the row types are mixed
132
61
 
133
- class << self
134
- # Reads and parses a CSV file from disk.
62
+ # @!method stream(csv_string, **options)
63
+ # Returns a {ZLight::StreamReader} over a CSV string.
135
64
  #
136
- # Convenience method that reads the file contents and passes them to {.parse}.
137
- # The file is read with UTF-8 encoding.
65
+ # Defined in the native extension; see ext/zlight_csv/src/read/stream.rs.
66
+ # Takes the same options as {.parse}.
138
67
  #
139
- # @param path [String] Path to the CSV file
140
- # @param headers [Boolean] Treat first row as headers (default: true)
141
- # @param converters [Symbol, nil] Set to :numeric for auto-conversion
142
- # @param col_sep [String] Column separator character (default: ",")
143
- # @param quote_char [String] Quote character for escaping (default: '"')
144
- # @param flexible [Boolean] Allow variable-length records (default: true)
145
- #
146
- # @return [Array<Hash>] When headers: true, returns array of Hashes with Symbol keys
147
- # @return [Array<Array>] When headers: false, returns array of Arrays
148
- #
149
- # @raise [Errno::ENOENT] If the file does not exist
150
- # @raise [ArgumentError] If options are invalid
151
- # @raise [ZLight::ParseError] If CSV data is malformed
68
+ # @return [ZLight::StreamReader] a single-pass reader
69
+
70
+ # @!method stream_file(path, **options)
71
+ # Returns a {ZLight::StreamReader} over a file.
152
72
  #
153
- # @example Read a CSV file with headers
154
- # ZLight.read("users.csv")
155
- # # => [{:name=>"Alice", :age=>"30"}, ...]
73
+ # Defined in the native extension. The file is opened immediately, so a
74
+ # missing or unreadable path raises here rather than on the first read.
75
+ # Prefer {.open}, which closes the reader for you.
156
76
  #
157
- # @example Read with numeric conversion
158
- # ZLight.read("users.csv", converters: :numeric)
159
- # # => [{:name=>"Alice", :age=>30}, ...]
77
+ # @return [ZLight::StreamReader] a single-pass reader
78
+ # @raise [IOError] if the file does not exist or cannot be read
79
+
80
+ # Reads and parses a CSV file.
160
81
  #
161
- # @example Read a TSV file
162
- # ZLight.read("data.tsv", col_sep: "\t")
82
+ # Convenience wrapper: reads the file as UTF-8 and hands it to {.parse},
83
+ # so the whole file is held in memory. Use {.open} for large files.
163
84
  #
85
+ # @param path [String] path to the CSV file
86
+ # @param options [Hash] any option accepted by {.parse}
87
+ # @return [Array<Hash>, Array<Array>] one element per row
88
+ # @raise [Errno::ENOENT] if the file does not exist
164
89
  # @see .parse
165
90
  def read(path, **options)
166
91
  parse(File.read(path, encoding: 'UTF-8'), **options)
167
92
  end
168
93
 
169
- # Writes CSV data to a file.
170
- #
171
- # Convenience method that generates CSV and writes to disk.
172
- # The file is written with UTF-8 encoding.
173
- #
174
- # @param path [String] Path to the output CSV file
175
- # @param rows [Array<Hash>, Array<Array>] The data to write
176
- # @param headers [Boolean] Write header row for hash input (default: true)
177
- # @param col_sep [String] Column separator character (default: ",")
178
- # @param quote_char [String] Quote character for escaping (default: '"')
179
- # @param force_quotes [Boolean] Force quoting all fields (default: false)
180
- #
181
- # @return [Integer] Number of bytes written
182
- #
183
- # @raise [Errno::ENOENT] If the directory does not exist
184
- # @raise [Errno::EACCES] If the file is not writable
185
- # @raise [ArgumentError] If options are invalid
94
+ # Writes rows to a CSV file.
186
95
  #
187
- # @example Write hashes to CSV
188
- # ZLight.write("users.csv", [{name: "Alice", age: 30}])
189
- #
190
- # @example Write arrays to CSV
191
- # ZLight.write("data.csv", [["a", "b"], [1, 2]])
192
- #
193
- # @example Write TSV
194
- # ZLight.write("data.tsv", rows, col_sep: "\t")
96
+ # Convenience wrapper around {.generate}. The CSV is built in memory before
97
+ # being written, so this is not suited to output larger than RAM.
195
98
  #
99
+ # @param path [String] path to write to
100
+ # @param rows [Array<Hash>, Array<Array>] the rows to write
101
+ # @param options [Hash] any option accepted by {.generate}
102
+ # @return [Integer] bytes written
103
+ # @raise [Errno::ENOENT] if the directory does not exist
196
104
  # @see .generate
197
105
  def write(path, rows, **options)
198
106
  File.write(path, generate(rows, **options), encoding: 'UTF-8')
199
107
  end
200
108
 
201
- # Iterates over each row in the CSV string.
202
- #
203
- # When called with a block, yields each row and returns nil.
204
- # When called without a block, returns an Enumerator for lazy iteration.
205
- #
206
- # @param csv_string [String] The CSV data to parse
207
- # @param headers [Boolean] Treat first row as headers (default: true)
208
- # @param converters [Symbol, nil] Set to :numeric for auto-conversion
209
- # @param col_sep [String] Column separator character (default: ",")
210
- # @param quote_char [String] Quote character for escaping (default: '"')
211
- # @param flexible [Boolean] Allow variable-length records (default: true)
109
+ # Iterates over the rows of a CSV string.
212
110
  #
213
- # @yield [row] Yields each row to the block
214
- # @yieldparam row [Hash, Array] A single row (Hash with headers, Array without)
215
- #
216
- # @return [nil] When a block is given
217
- # @return [Enumerator] When no block is given, for lazy iteration
218
- #
219
- # @example Iterate with a block
220
- # ZLight.foreach("name,age\nAlice,30\nBob,25") do |row|
221
- # puts row[:name]
222
- # end
223
- # # Output:
224
- # # Alice
225
- # # Bob
226
- #
227
- # @example Use as Enumerator
228
- # names = ZLight.foreach("name,age\nAlice,30").map { |row| row[:name] }
229
- # # => ["Alice"]
230
- #
231
- # @example Chain with Enumerable methods
232
- # adults = ZLight.foreach(csv_data, converters: :numeric)
233
- # .select { |row| row[:age] >= 18 }
234
- # .map { |row| row[:name] }
111
+ # Note that unlike `CSV.foreach`, this takes a **string, not a path**, and
112
+ # parses the whole input before yielding. For lazy iteration use {.open}.
235
113
  #
114
+ # @param csv_string [String] the CSV data
115
+ # @param options [Hash] any option accepted by {.parse}
116
+ # @yieldparam row [Hash, Array] each row in turn
117
+ # @return [nil, Enumerator] an Enumerator when no block is given
236
118
  # @see .parse
237
- def foreach(csv_string, **options, &block)
119
+ def foreach(csv_string, **options, &)
238
120
  return to_enum(:foreach, csv_string, **options) unless block_given?
239
121
 
240
- parse(csv_string, **options).each(&block)
122
+ parse(csv_string, **options).each(&)
241
123
  end
242
124
 
243
- # Creates a streaming reader for a CSV file with automatic resource management.
244
- #
245
- # This is the most memory-efficient way to process large CSV files.
246
- # Rows are read one at a time directly from disk.
247
- #
248
- # When called with a block, automatically closes the reader after
249
- # the block completes (even if an exception is raised).
250
- #
251
- # @param path [String] Path to the CSV file
252
- # @param headers [Boolean] Treat first row as headers (default: true)
253
- # @param converters [Symbol, nil] Set to :numeric for auto-conversion
254
- # @param col_sep [String] Column separator character (default: ",")
255
- # @param quote_char [String] Quote character (default: '"')
256
- # @param flexible [Boolean] Allow variable-length records (default: true)
257
- #
258
- # @yield [reader] If a block is given, yields the reader and auto-closes
259
- # @yieldparam reader [ZLight::StreamReader] The streaming reader
260
- #
261
- # @return [ZLight::StreamReader] The streaming reader (if no block)
262
- # @return [Object] The block's return value (if block given)
263
- #
264
- # @raise [Errno::ENOENT] If the file does not exist
265
- # @raise [Errno::EACCES] If the file is not readable
266
- #
267
- # @example Process a large file row by row
268
- # ZLight.open("users.csv") do |reader|
269
- # reader.each do |row|
270
- # User.create!(name: row[:name], email: row[:email])
271
- # end
272
- # end
273
- #
274
- # @example Get first 100 matching rows lazily
275
- # ZLight.open("data.csv", converters: :numeric) do |reader|
276
- # reader.lazy
277
- # .select { |row| row[:score] > 90 }
278
- # .first(100)
279
- # end
280
- #
281
- # @example Manual resource management
282
- # reader = ZLight.open("large.csv")
283
- # begin
284
- # reader.each { |row| process(row) }
285
- # ensure
286
- # reader.close
125
+ # Streams a CSV file, closing the reader afterwards.
126
+ #
127
+ # The memory-efficient way to process a large file: rows are read one at a
128
+ # time rather than materialised up front. With a block the reader is closed
129
+ # when the block exits, including on an exception.
130
+ #
131
+ # @param path [String] path to the CSV file
132
+ # @param options [Hash] any option accepted by {.parse}
133
+ # @yieldparam reader [ZLight::StreamReader] the reader
134
+ # @return [Object, ZLight::StreamReader] the block's value, or the reader
135
+ # itself when no block is given, in which case you must close it
136
+ # @raise [IOError] if the file does not exist or cannot be read
137
+ #
138
+ # @example Stop early without reading the rest of the file
139
+ # ZLight.open("huge.csv", converters: :numeric) do |reader|
140
+ # reader.lazy.select { |row| row[:score] > 90 }.first(100)
287
141
  # end
288
142
  #
289
143
  # @see ZLight::StreamReader
290
144
  def open(path, **options)
291
145
  reader = stream_file(path, **options)
146
+ return reader unless block_given?
292
147
 
293
- if block_given?
294
- begin
295
- yield reader
296
- ensure
297
- reader.close unless reader.closed?
298
- end
299
- else
300
- reader
148
+ begin
149
+ yield reader
150
+ ensure
151
+ reader.close unless reader.closed?
301
152
  end
302
153
  end
303
154
  end
155
+
156
+ # A single-pass reader over a CSV source, yielding one row at a time.
157
+ #
158
+ # Defined in the native extension; see ext/zlight_csv/src/read/stream.rs.
159
+ # Obtained from {ZLight.stream}, {ZLight.stream_file} or {ZLight.open}.
160
+ #
161
+ # Includes `Enumerable`, so `map`, `select`, `find` and `lazy` all work — but
162
+ # the reader is **single-pass**: each row is consumed as it is read, so a
163
+ # second enumeration yields nothing and there is no rewind.
164
+ #
165
+ # @!method next_row
166
+ # @return [Hash, Array, nil] the next row, or nil once exhausted
167
+ # @raise [ZLight::StreamClosedError] if the reader has been closed
168
+ # @!method each
169
+ # @yieldparam row [Hash, Array] each row in turn
170
+ # @return [self, Enumerator] an Enumerator when no block is given
171
+ # @!method headers
172
+ # @return [Array<Symbol>, nil] the header symbols, or nil without headers
173
+ # @!method close
174
+ # Releases the underlying file or buffer. Idempotent.
175
+ # @return [nil]
176
+ # @!method closed?
177
+ # @return [Boolean]
178
+ # @!method eof?
179
+ # @return [Boolean] true once exhausted or closed
180
+ # Reopened solely to attach the documentation above; the class itself and
181
+ # all of its methods come from the extension.
182
+ class StreamReader; end # rubocop:disable Lint/EmptyClass
304
183
  end
metadata CHANGED
@@ -1,18 +1,33 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zlight_csv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - Zaidan Chaudhary
8
+ - Saad Chaudhary
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2026-06-06 00:00:00.000000000 Z
12
- dependencies: []
12
+ date: 2026-09-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rb_sys
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.9'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.9'
13
28
  description: |
14
29
  ZLight brings the speed of Rust to Ruby's CSV parsing. Built as a native
15
- extension, it delivers up to 30x faster performance than Ruby's standard
30
+ extension, it delivers up to 40x faster performance than Ruby's standard
16
31
  CSV library while maintaining full API compatibility. Whether you're parsing
17
32
  small configuration files or processing millions of rows, ZLight handles it
18
33
  efficiently. The streaming API enables memory-efficient processing of large
@@ -24,22 +39,36 @@ executables: []
24
39
  extensions: []
25
40
  extra_rdoc_files: []
26
41
  files:
42
+ - ARCHITECTURE.md
27
43
  - CHANGELOG.md
28
44
  - LICENSE
29
45
  - README.md
30
46
  - VERSION
47
+ - ext/zlight_csv/Cargo.toml
48
+ - ext/zlight_csv/extconf.rb
49
+ - ext/zlight_csv/src/convert.rs
50
+ - ext/zlight_csv/src/error.rs
51
+ - ext/zlight_csv/src/lib.rs
52
+ - ext/zlight_csv/src/options.rs
53
+ - ext/zlight_csv/src/reader.rs
54
+ - ext/zlight_csv/src/row.rs
31
55
  - lib/zlight_csv.rb
32
- - lib/zlight_csv/3.0/zlight_csv.so
33
56
  - lib/zlight_csv/3.1/zlight_csv.so
34
57
  - lib/zlight_csv/3.2/zlight_csv.so
35
58
  - lib/zlight_csv/3.3/zlight_csv.so
59
+ - lib/zlight_csv/3.4/zlight_csv.so
60
+ - lib/zlight_csv/4.0/zlight_csv.so
61
+ - lib/zlight_csv/errors.rb
62
+ - lib/zlight_csv/native.rb
36
63
  - lib/zlight_csv/version.rb
37
- homepage: https://rubygems.org/gems/zlight_csv
64
+ homepage: https://github.com/codebyisaad/zlight
38
65
  licenses:
39
66
  - MIT
40
67
  metadata:
41
- homepage_uri: https://rubygems.org/gems/zlight_csv
42
- documentation_uri: https://zaidanch.github.io/zlight-docs/
68
+ source_code_uri: https://github.com/codebyisaad/zlight
69
+ changelog_uri: https://github.com/codebyisaad/zlight/blob/main/CHANGELOG.md
70
+ bug_tracker_uri: https://github.com/codebyisaad/zlight/issues
71
+ documentation_uri: https://codebyisaad.github.io/zlight-docs/
43
72
  rubygems_mfa_required: 'true'
44
73
  post_install_message:
45
74
  rdoc_options: []
@@ -49,10 +78,10 @@ required_ruby_version: !ruby/object:Gem::Requirement
49
78
  requirements:
50
79
  - - ">="
51
80
  - !ruby/object:Gem::Version
52
- version: '3.0'
81
+ version: '3.1'
53
82
  - - "<"
54
83
  - !ruby/object:Gem::Version
55
- version: 3.4.dev
84
+ version: 4.1.dev
56
85
  required_rubygems_version: !ruby/object:Gem::Requirement
57
86
  requirements:
58
87
  - - ">="
Binary file