aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@unit193.net>2025-11-26 19:02:46 -0500
committerLibravatarUnit 193 <unit193@unit193.net>2025-11-26 19:02:46 -0500
commitc77a15eed515fe6dc9b2e831670f4d484e23dace (patch)
tree87c79155c0b52b0e59eaf971f2b5bf9d860c77e4
parent537c7673bedbb1a2f77a3a088710546cb46506d0 (diff)
parentc62f8376a13e7a4f493167aba1c66a9201fc59c6 (diff)
Update upstream source from tag 'upstream/3.0.0'
Update to upstream version '3.0.0' with Debian dir ceed7b02bc1417ad11993c466d2350a6b62fbecf
-rw-r--r--.codeclimate.yml17
-rw-r--r--.github/pull_request_template.md20
-rw-r--r--.github/workflows/pull-request.yml15
-rw-r--r--.github/workflows/release-please.yml52
-rw-r--r--.github/workflows/ruby.yml16
-rw-r--r--.gitignore3
-rw-r--r--.release-please-manifest.json3
-rw-r--r--.rubocop.yml19
-rw-r--r--CHANGELOG.md38
-rw-r--r--[-rwxr-xr-x]Gemfile7
-rw-r--r--README.md48
-rw-r--r--checksums/roo-2.10.1.gem.sha5121
-rw-r--r--lib/roo/base.rb8
-rwxr-xr-xlib/roo/excelx.rb12
-rw-r--r--lib/roo/excelx/cell/number.rb2
-rw-r--r--lib/roo/excelx/comments.rb2
-rw-r--r--lib/roo/formatters/csv.rb10
-rw-r--r--lib/roo/formatters/yaml.rb2
-rw-r--r--lib/roo/open_office.rb4
-rw-r--r--lib/roo/spreadsheet.rb2
-rw-r--r--lib/roo/tempdir.rb5
-rw-r--r--lib/roo/utils.rb3
-rw-r--r--lib/roo/version.rb2
-rw-r--r--release-please-config.json12
-rw-r--r--roo.gemspec21
-rw-r--r--spec/lib/roo/base_spec.rb36
-rw-r--r--spec/spec_helper.rb11
-rw-r--r--test/excelx/cell/test_number.rb5
-rw-r--r--test/files/comments-with-author.xlsxbin0 -> 12524 bytes
-rw-r--r--test/helpers/test_accessing_files.rb21
-rw-r--r--test/helpers/test_comments.rb11
-rw-r--r--test/roo/test_open_office.rb2
-rw-r--r--test/test_helper.rb4
-rw-r--r--test/test_roo.rb2
34 files changed, 309 insertions, 107 deletions
diff --git a/.codeclimate.yml b/.codeclimate.yml
deleted file mode 100644
index 7cdba5f..0000000
--- a/.codeclimate.yml
+++ /dev/null
@@ -1,17 +0,0 @@
----
-engines:
- duplication:
- enabled: true
- config:
- languages:
- - ruby
- fixme:
- enabled: true
- rubocop:
- enabled: true
-ratings:
- paths:
- - "**.rb"
-exclude_paths:
-- spec/
-- test/
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index a0d7f6e..6e152a1 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,3 +1,21 @@
+<!--
+Thank you for your contribution!
+
+Please ensure your pull request title follows the Conventional Commits format.
+This is important because our release process is automated based on the commit messages.
+
+Examples:
+- feat: Add new feature
+- fix: Fix a bug
+- docs: Update documentation
+- chore: Build process or auxiliary tool changes
+- refactor: A code change that neither fixes a bug nor adds a feature
+- style: Changes that do not affect the meaning of the code (white-space, formatting, etc)
+- test: Adding missing tests or correcting existing tests
+
+If your change is a breaking change, please add a '!' after the type, e.g., 'feat!: ...'
+-->
+
### Summary
Provide a general description of the code changes in your pull
@@ -11,4 +29,4 @@ If there's anything else that's important and relevant to your pull
request, mention that information here. This could include
benchmarks, or other information.
-Thanks for contributing to Roo! \ No newline at end of file
+Thanks for contributing to Roo!
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
deleted file mode 100644
index 9d94c4b..0000000
--- a/.github/workflows/pull-request.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: Changelog
-
-on:
- pull_request:
- types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
-
-jobs:
- changelog:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - uses: amoniacou/changelog-enforcer@v1.4.0
- with:
- changeLogPath: 'CHANGELOG.md'
- skipLabel: 'Skip-Changelog'
diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml
new file mode 100644
index 0000000..3f8f67a
--- /dev/null
+++ b/.github/workflows/release-please.yml
@@ -0,0 +1,52 @@
+name: Release Please
+
+on:
+ push:
+ branches:
+ - master
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ release-please:
+ runs-on: ubuntu-latest
+ outputs:
+ release_created: ${{ steps.release.outputs.release_created }}
+ tag_name: ${{ steps.release.outputs.tag_name }}
+ steps:
+ - uses: googleapis/release-please-action@v4
+ id: release
+ with:
+ config-file: release-please-config.json
+ manifest-file: .release-please-manifest.json
+
+ publish:
+ needs: release-please
+ if: ${{ needs.release-please.outputs.release_created }}
+ runs-on: ubuntu-latest
+ environment: PUBLISH
+ permissions:
+ contents: write
+ id-token: write
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ needs.release-please.outputs.tag_name }}
+ fetch-tags: true
+
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: '3.4'
+ bundler-cache: true
+
+ - name: Publish to RubyGems
+ uses: rubygems/release-gem@v1
+
+ - name: Upload Gem to GitHub Release
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: gh release upload ${{ needs.release-please.outputs.tag_name }} ./*.gem --clobber \ No newline at end of file
diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml
index 6892090..9fe5129 100644
--- a/.github/workflows/ruby.yml
+++ b/.github/workflows/ruby.yml
@@ -6,6 +6,11 @@ on:
pull_request:
branches:
- master
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
jobs:
build:
runs-on: ubuntu-latest
@@ -13,17 +18,19 @@ jobs:
fail-fast: false
matrix:
ruby:
- - '2.7'
- - '3.0'
- '3.1'
+ - '3.2'
+ - '3.3'
+ - '3.4'
+ - '3.5'
- ruby-head
- - jruby-9.3.3.0
+ - jruby-9.4.10.0
include:
- ruby: ruby-head
env:
RUBYOPT: '--jit'
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
@@ -31,4 +38,3 @@ jobs:
- run: bundle exec rake
env:
LONG_RUN: true
-
diff --git a/.gitignore b/.gitignore
index 1f42a9a..339b944 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,4 +8,5 @@
.buildpath
*~
.bundle/
-lbin/ \ No newline at end of file
+lbin/
+vendor
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
new file mode 100644
index 0000000..d4f6f29
--- /dev/null
+++ b/.release-please-manifest.json
@@ -0,0 +1,3 @@
+{
+ ".": "3.0.0"
+}
diff --git a/.rubocop.yml b/.rubocop.yml
index e6ce1a7..46b9cb8 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -1,8 +1,11 @@
+require: rubocop-performance
+
AllCops:
- TargetRubyVersion: 2.4
+ TargetRubyVersion: 3.1
# RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
# to ignore them, so only the ones explicitly set in this file are enabled.
DisabledByDefault: true
+ SuggestExtensions: false
Performance:
Exclude:
@@ -13,12 +16,6 @@ Performance:
Style/AndOr:
Enabled: true
-# Do not use braces for hash literals when they are the last argument of a
-# method call.
-Style/BracesAroundHashParameters:
- Enabled: true
- EnforcedStyle: context_dependent
-
# Align `when` with `case`.
Layout/CaseIndentation:
Enabled: true
@@ -127,11 +124,11 @@ Style/StringLiterals:
EnforcedStyle: double_quotes
# Detect hard tabs, no hard tabs.
-Layout/Tab:
+Layout/IndentationStyle:
Enabled: true
# Blank lines should not have any spaces.
-Layout/TrailingBlankLines:
+Layout/TrailingEmptyLines:
Enabled: true
# No trailing whitespace.
@@ -139,14 +136,14 @@ Layout/TrailingWhitespace:
Enabled: true
# Use quotes for string literals when they are enough.
-Style/UnneededPercentQ:
+Style/RedundantPercentQ:
Enabled: true
# Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
Lint/RequireParentheses:
Enabled: true
-Lint/StringConversionInInterpolation:
+Lint/RedundantStringCoercion:
Enabled: true
Lint/UriEscapeUnescape:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 30a4704..85c878d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,15 +1,39 @@
-## Unreleased
+## Unreleased
+
+## [3.0.0](https://github.com/roo-rb/roo/compare/v2.10.1...v3.0.0) (2025-10-01)
+
+### Miscellaneous Chores
+
+* release 3.0.0 ([82619d3](https://github.com/roo-rb/roo/commit/82619d33929fd51411d173fbedd8a9c8136b4f72))
+
+### Changed/Added
+
+- Add dependencies for `csv` and `base64` if Ruby version higher or equal 3.4 [616](https://github.com/roo-rb/roo/pull/616)
+- Add dependency for `logger` if Ruby version higher or equal 3.4 [618](https://github.com/roo-rb/roo/pull/618)
+- Add changelog link to gemspec [605](https://github.com/roo-rb/roo/pull/605)
+- Upgraded rack via usage of rackup
+- Resolve deprecation warnings about uri DEFAULT_PARSER
+- Add support for rubyzip 3.x [629](https://github.com/roo-rb/roo/pull/629)
+
+### Removed
+
+- Support for ruby 2.7, 3.0
+- Support for rubyzip < 3.x
+
+## [2.10.1] 2024-01-17
### Changed/Added
+- Prevent warnings on Ruby 3.1 if finalizer is called twice [586](https://github.com/roo-rb/roo/pull/586)
+- Fix Roo::Base#each_with_pagename degraded at [576](https://github.com/roo-rb/roo/pull/576) [583](https://github.com/roo-rb/roo/pull/583)
-## [2.10.0] 2023-02-07
+## [2.10.0] 2023-02-07
### Changed/Added
- Fix gsub! usage for open office documents on a frozen string [581](https://github.com/roo-rb/roo/pull/581)
- Add support for boolean values in open office files that were generated via Google Sheets [580](https://github.com/roo-rb/roo/pull/580)
- Roo::Base#each_with_pagename returns Enumerator Object [576](https://github.com/roo-rb/roo/pull/576)
-## [2.9.0] 2022-03-19
+## [2.9.0] 2022-03-19
### Changed/Added
- Ruby 3.x Support [555](https://github.com/roo-rb/roo/pull/555)
@@ -23,11 +47,11 @@
### Removed
- Support for ruby 2.4, 2.5, 2.6(excluded jRuby)
-## [2.8.3] 2020-02-03
+## [2.8.3] 2020-02-03
### Changed/Added
- Updated rubyzip version. Now minimal version is 1.3.0 [515](https://github.com/roo-rb/roo/pull/515) - [CVE-2019-16892](https://github.com/rubyzip/rubyzip/pull/403)
-## [2.8.2] 2019-02-01
+## [2.8.2] 2019-02-01
### Changed/Added
- Support range cell for Excelx's links [490](https://github.com/roo-rb/roo/pull/490)
- Skip `extract_hyperlinks` if not required [488](https://github.com/roo-rb/roo/pull/488)
@@ -35,11 +59,11 @@
### Fixed
- Fixed error for invalid link [492](https://github.com/roo-rb/roo/pull/492)
-## [2.8.1] 2019-01-21
+## [2.8.1] 2019-01-21
### Fixed
- Fixed error if excelx's cell have empty children [487](https://github.com/roo-rb/roo/pull/487)
-## [2.8.0] 2019-01-18
+## [2.8.0] 2019-01-18
### Fixed
- Fixed inconsistent column length for CSV [375](https://github.com/roo-rb/roo/pull/375)
- Fixed formatted_value with `%` for Excelx [416](https://github.com/roo-rb/roo/pull/416)
diff --git a/Gemfile b/Gemfile
index e3fd903..4660510 100755..100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,15 +2,18 @@ source 'https://rubygems.org'
gemspec
+gem 'rubocop'
+gem 'rubocop-performance', require: false
+
group :test do
# additional testing libs
gem 'shoulda'
- gem 'activesupport', '< 5.1'
+ gem 'activesupport'
gem 'rspec', '>= 3.0.0'
gem 'simplecov', '>= 0.9.0', require: false
gem 'coveralls', require: false
gem "minitest-reporters"
- gem 'webrick' if RUBY_VERSION >= '3.0.0'
+ gem 'webrick'
end
group :local_development do
diff --git a/README.md b/README.md
index 021afb4..be3016f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Roo
-[![Build Status](https://img.shields.io/travis/roo-rb/roo.svg?style=flat-square)](https://travis-ci.org/roo-rb/roo) [![Maintainability](https://api.codeclimate.com/v1/badges/be8d7bf34e2aeaf67c62/maintainability)](https://codeclimate.com/github/roo-rb/roo/maintainability) [![Coverage Status](https://img.shields.io/coveralls/roo-rb/roo.svg?style=flat-square)](https://coveralls.io/r/roo-rb/roo) [![Gem Version](https://img.shields.io/gem/v/roo.svg?style=flat-square)](https://rubygems.org/gems/roo)
+[![Build Status](https://img.shields.io/github/actions/workflow/status/roo-rb/roo/ruby.yml?style=flat-square)](https://travis-ci.org/roo-rb/roo) [![Maintainability](https://api.codeclimate.com/v1/badges/be8d7bf34e2aeaf67c62/maintainability)](https://codeclimate.com/github/roo-rb/roo/maintainability) [![Coverage Status](https://img.shields.io/coveralls/roo-rb/roo.svg?style=flat-square)](https://coveralls.io/r/roo-rb/roo) [![Gem Version](https://img.shields.io/gem/v/roo.svg?style=flat-square)](https://rubygems.org/gems/roo)
Roo implements read access for all common spreadsheet types. It can handle:
* Excel 2007 - 2013 formats (xlsx, xlsm)
@@ -9,6 +9,11 @@ Roo implements read access for all common spreadsheet types. It can handle:
* Excel 97, Excel 2002 XML, and Excel 2003 XML formats when using the [roo-xls](https://github.com/roo-rb/roo-xls) gem (xls, xml)
* Google spreadsheets with read/write access when using [roo-google](https://github.com/roo-rb/roo-google)
+## Important note about next major release
+
+There a plan to make a new major release which will have better support for Ruby 3.x
+Please leave your comments there - https://github.com/roo-rb/roo/issues/630
+
## Installation
Install as a gem
@@ -18,26 +23,41 @@ Install as a gem
Or add it to your Gemfile
```ruby
-gem "roo", "~> 2.9.0"
+gem "roo", "~> 3.0.0"
```
## Usage
-Opening a spreadsheet
+### Opening a spreadsheet
+You can use the `Roo::Spreadsheet` class so `roo` automatically detects which [parser class](https://github.com/roo-rb/roo/blob/master/lib/roo.rb#L17) to use for you.
```ruby
require 'roo'
-xlsx = Roo::Spreadsheet.open('./new_prices.xlsx')
-xlsx = Roo::Excelx.new("./new_prices.xlsx")
+file_name = './new_prices.xlsx'
+xlsx = Roo::Spreadsheet.open(file_name)
+xlsx.info
+# => Returns basic info about the spreadsheet file
+```
-# Use the extension option if the extension is ambiguous.
-xlsx = Roo::Spreadsheet.open('./rails_temp_upload', extension: :xlsx)
+``Roo::Spreadsheet.open`` can accept both string paths and ``File`` instances. Also, you can provide the extension of the file as an option:
+```ruby
+require 'roo'
+
+file_name = './rails_temp_upload'
+xlsx = Roo::Spreadsheet.open(file_name, extension: :xlsx)
xlsx.info
# => Returns basic info about the spreadsheet file
```
-``Roo::Spreadsheet.open`` can accept both paths and ``File`` instances.
+On the other hand, if you know what the file extension is, you can use the specific parser class instead:
+```ruby
+require 'roo'
+
+xlsx = Roo::Excelx.new("./new_prices.xlsx")
+xlsx.info
+# => Returns basic info about the spreadsheet file
+```
### Working with sheets
@@ -156,6 +176,18 @@ sheet.to_xml
sheet.to_yaml
```
+Specify the file as default argument for `#to_csv`:
+
+```ruby
+sheet.to_csv(File.new("/dev/null"))
+```
+
+specify the custom separator:
+
+```ruby
+sheet.to_csv(separator: ":") # "," using by default
+```
+
### Excel (xlsx and xlsm) Support
Stream rows from an Excelx spreadsheet.
diff --git a/checksums/roo-2.10.1.gem.sha512 b/checksums/roo-2.10.1.gem.sha512
new file mode 100644
index 0000000..7132c7e
--- /dev/null
+++ b/checksums/roo-2.10.1.gem.sha512
@@ -0,0 +1 @@
+bc12fbc27e9d8423e4a84eee9eaf1192c368f5c490e3b8ae0c6c65a5c0828e908d775ddb57100fa5a4c9c9b849511930e8324868ef5d61d916a2398ba9520382
diff --git a/lib/roo/base.rb b/lib/roo/base.rb
index 91c8d1c..80b495e 100644
--- a/lib/roo/base.rb
+++ b/lib/roo/base.rb
@@ -250,10 +250,10 @@ class Roo::Base
# iterate through all worksheets of a document
def each_with_pagename
- Enumerator.new do |yielder|
- sheets.each do |s|
- yielder << sheet(s, true)
- end
+ return to_enum(:each_with_pagename) { sheets.size } unless block_given?
+
+ sheets.each do |s|
+ yield sheet(s, true)
end
end
diff --git a/lib/roo/excelx.rb b/lib/roo/excelx.rb
index 91ebc1e..14a6b4f 100755
--- a/lib/roo/excelx.rb
+++ b/lib/roo/excelx.rb
@@ -333,7 +333,7 @@ module Roo
wb = entries.find { |e| e.name[/workbook.xml$/] }
fail ArgumentError 'missing required workbook file' if wb.nil?
- wb.extract(path)
+ wb.extract(File.basename(path), destination_directory: File.dirname(path))
workbook_doc = Roo::Utils.load_xml(path).remove_namespaces!
workbook_doc.xpath('//sheet').map { |s| s['id'] }
end
@@ -357,7 +357,7 @@ module Roo
wb_rels = entries.find { |e| e.name[/workbook.xml.rels$/] }
fail ArgumentError 'missing required workbook file' if wb_rels.nil?
- wb_rels.extract(path)
+ wb_rels.extract(File.basename(path), destination_directory: File.dirname(path))
rels_doc = Roo::Utils.load_xml(path).remove_namespaces!
relationships = rels_doc.xpath('//Relationship').select do |relationship|
@@ -378,7 +378,7 @@ module Roo
path = "#{tmpdir}/roo_sheet#{i + 1}"
sheet_files << path
@sheet_files << path
- entry.extract(path)
+ entry.extract(File.basename(path), destination_directory: File.dirname(path))
end
end
@@ -387,7 +387,7 @@ module Roo
img_entries.each do |entry|
path = "#{@tmpdir}/roo#{entry.name.gsub(/xl\/|\//, "_")}"
image_files << path
- entry.extract(path)
+ entry.extract(File.basename(path), destination_directory: File.dirname(path))
end
end
@@ -402,7 +402,7 @@ module Roo
zip_file.read_from_stream zipfilename_or_stream
end
- process_zipfile_entries zip_file.to_a.sort_by(&:name)
+ process_zipfile_entries zip_file.entries.sort_by(&:name)
end
def process_zipfile_entries(entries)
@@ -462,7 +462,7 @@ module Roo
image_rels[nr - 1] = "#{@tmpdir}/roo_image_rels#{nr}"
end
- entry.extract(path) if path
+ entry.extract(File.basename(path), destination_directory: File.dirname(path)) if path
end
end
diff --git a/lib/roo/excelx/cell/number.rb b/lib/roo/excelx/cell/number.rb
index 5cd9b55..5cdec5e 100644
--- a/lib/roo/excelx/cell/number.rb
+++ b/lib/roo/excelx/cell/number.rb
@@ -51,7 +51,7 @@ module Roo
when /^#,##0.(0+)$/ then number_format("%.#{$1.size}f")
when '0%'
proc do |number|
- Kernel.format('%d%%', number.to_f * 100)
+ Kernel.format('%.0f%%', number.to_f * 100)
end
when '0.00%'
proc do |number|
diff --git a/lib/roo/excelx/comments.rb b/lib/roo/excelx/comments.rb
index 65044a9..c37097a 100644
--- a/lib/roo/excelx/comments.rb
+++ b/lib/roo/excelx/comments.rb
@@ -13,7 +13,7 @@ module Roo
return {} unless doc_exists?
doc.xpath('//comments/commentList/comment').each_with_object({}) do |comment, hash|
- value = (comment.at_xpath('./text/r/t') || comment.at_xpath('./text/t')).text
+ value = comment.xpath('./text/r/t', './text/t').text
hash[::Roo::Utils.ref_to_key(comment['ref'].to_s)] = value
end
end
diff --git a/lib/roo/formatters/csv.rb b/lib/roo/formatters/csv.rb
index 3181f09..67f63fa 100644
--- a/lib/roo/formatters/csv.rb
+++ b/lib/roo/formatters/csv.rb
@@ -1,7 +1,15 @@
module Roo
module Formatters
module CSV
- def to_csv(filename = nil, separator = ",", sheet = default_sheet)
+ def to_csv(filename = nil, old_separator = nil, old_sheet = nil, separator: ",", sheet: default_sheet)
+ if old_separator
+ warn("[DEPRECATION] optional argument for separator is deprecated. Please use keyword argument :separator instead")
+ separator = old_separator
+ end
+ if old_sheet
+ warn("[DEPRECATION] optional argument for sheet is deprecated. Please use keyword argument :sheet instead")
+ sheet = old_sheet
+ end
if filename
File.open(filename, "w") do |file|
write_csv_content(file, sheet, separator)
diff --git a/lib/roo/formatters/yaml.rb b/lib/roo/formatters/yaml.rb
index 69ef3ab..090b334 100644
--- a/lib/roo/formatters/yaml.rb
+++ b/lib/roo/formatters/yaml.rb
@@ -13,7 +13,7 @@ module Roo
from_column ||= first_column(sheet)
to_column ||= last_column(sheet)
- result = "--- \n"
+ result = String.new("--- \n")
from_row.upto(to_row) do |row|
from_column.upto(to_column) do |col|
next if empty?(row, col, sheet)
diff --git a/lib/roo/open_office.rb b/lib/roo/open_office.rb
index 542c5b4..f7a8139 100644
--- a/lib/roo/open_office.rb
+++ b/lib/roo/open_office.rb
@@ -59,7 +59,7 @@ module Roo
fail ArgumentError, ERROR_MISSING_CONTENT_XML unless content_entry
roo_content_xml_path = ::File.join(@tmpdir, 'roo_content.xml')
- content_entry.extract(roo_content_xml_path)
+ content_entry.extract('roo_content.xml', destination_directory: @tmpdir)
decrypt_if_necessary(zip_file, content_entry, roo_content_xml_path, options)
end
end
@@ -234,7 +234,7 @@ module Roo
if (manifest_entry = zip_file.glob('META-INF/manifest.xml').first)
roo_manifest_xml_path = File.join(@tmpdir, 'roo_manifest.xml')
- manifest_entry.extract(roo_manifest_xml_path)
+ manifest_entry.extract('roo_manifest.xml', destination_directory: @tmpdir)
manifest = ::Roo::Utils.load_xml(roo_manifest_xml_path)
# XPath search for manifest:encryption-data only for the content.xml
diff --git a/lib/roo/spreadsheet.rb b/lib/roo/spreadsheet.rb
index 54063b6..909dd62 100644
--- a/lib/roo/spreadsheet.rb
+++ b/lib/roo/spreadsheet.rb
@@ -25,7 +25,7 @@ module Roo
extension.tr('.', '').downcase.to_sym
else
parsed_path =
- if path =~ /\A#{::URI::DEFAULT_PARSER.make_regexp}\z/
+ if path =~ /\A#{::Roo::Utils::URI_PARSER.make_regexp}\z/
# path is 7th match
Regexp.last_match[7]
else
diff --git a/lib/roo/tempdir.rb b/lib/roo/tempdir.rb
index 4be755b..7ad7989 100644
--- a/lib/roo/tempdir.rb
+++ b/lib/roo/tempdir.rb
@@ -4,7 +4,10 @@ module Roo
if @tempdirs && (dirs_to_remove = @tempdirs[object_id])
@tempdirs.delete(object_id)
dirs_to_remove.each do |dir|
- ::FileUtils.remove_entry(dir)
+ # Pass force=true to avoid an exception (and thus warnings in Ruby 3.1) if dir has
+ # already been removed. This can occur when the finalizer is called both in a forked
+ # child process and in the parent.
+ ::FileUtils.remove_entry(dir, true)
end
end
end
diff --git a/lib/roo/utils.rb b/lib/roo/utils.rb
index 2d6754a..9dcfd24 100644
--- a/lib/roo/utils.rb
+++ b/lib/roo/utils.rb
@@ -5,6 +5,7 @@ module Roo
extend self
LETTERS = ('A'..'Z').to_a
+ URI_PARSER = defined?(::URI::RFC2396_PARSER) ? ::URI::RFC2396_PARSER : ::URI::DEFAULT_PARSER
def extract_coordinate(s)
num = letter_num = 0
@@ -34,8 +35,6 @@ module Roo
extract_coordinate(str)
end
-
-
def split_coord(str)
coord = extract_coordinate(str)
[number_to_letter(coord.column), coord.row]
diff --git a/lib/roo/version.rb b/lib/roo/version.rb
index 0ad4acc..3adf0b7 100644
--- a/lib/roo/version.rb
+++ b/lib/roo/version.rb
@@ -1,3 +1,3 @@
module Roo
- VERSION = "2.10.0"
+ VERSION = "3.0.0"
end
diff --git a/release-please-config.json b/release-please-config.json
new file mode 100644
index 0000000..9978c9c
--- /dev/null
+++ b/release-please-config.json
@@ -0,0 +1,12 @@
+{
+ "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
+ "packages": {
+ ".": {
+ "version-file": "lib/roo/version.rb",
+ "release-type": "ruby",
+ "changelog-path": "CHANGELOG.md",
+ "include-component-in-tag": false,
+ "include-v-in-tag": true
+ }
+ }
+}
diff --git a/roo.gemspec b/roo.gemspec
index c6561c2..a733460 100644
--- a/roo.gemspec
+++ b/roo.gemspec
@@ -17,19 +17,22 @@ Gem::Specification.new do |spec|
spec.files.reject! { |fn| fn.include?('test/files') }
spec.require_paths = ['lib']
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
- spec.required_ruby_version = ">= 2.6.0"
- else
- spec.required_ruby_version = ">= 2.7.0"
+ spec.required_ruby_version = ">= 3.1.0"
+
+ if RUBY_VERSION >= '3.4.0'
+ spec.add_dependency 'base64', '~> 0.2'
+ spec.add_dependency 'csv', '~> 3'
+ spec.add_dependency 'logger', '~> 1'
end
spec.add_dependency 'nokogiri', '~> 1'
- spec.add_dependency 'rubyzip', '>= 1.3.0', '< 3.0.0'
+ spec.add_dependency 'rubyzip', '>= 3.0.0', '< 4.0.0'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'minitest', '~> 5.4', '>= 5.4.3'
- spec.add_development_dependency 'rack', '~> 1.6', '< 2.0.0'
- if RUBY_VERSION >= '3.0.0'
- spec.add_development_dependency 'matrix'
- end
+ spec.add_development_dependency 'rack', '>= 3.0.0'
+ spec.add_development_dependency 'rackup', '>= 2.2.1', '< 3.0.0'
+ spec.add_development_dependency 'matrix'
+
+ spec.metadata["changelog_uri"] = spec.homepage + '/blob/master/CHANGELOG.md'
end
diff --git a/spec/lib/roo/base_spec.rb b/spec/lib/roo/base_spec.rb
index 9d44656..2d8d8d7 100644
--- a/spec/lib/roo/base_spec.rb
+++ b/spec/lib/roo/base_spec.rb
@@ -183,10 +183,22 @@ describe Roo::Base do
end
describe '#each_with_pagename' do
- it 'should return an enumerator with all the rows' do
- each_with_pagename = spreadsheet.each_with_pagename
- expect(each_with_pagename).to be_a(Enumerator)
- expect(each_with_pagename.to_a.last).to eq([spreadsheet.default_sheet, spreadsheet])
+ context 'when block given' do
+ it 'iterate with sheet and sheet_name' do
+ sheet_names = []
+ spreadsheet.each_with_pagename do |sheet_name, sheet|
+ sheet_names << sheet_name
+ end
+ expect(sheet_names).to eq ['my_sheet', 'blank sheet']
+ end
+ end
+
+ context 'when called without block' do
+ it 'should return an enumerator with all the rows' do
+ each_with_pagename = spreadsheet.each_with_pagename
+ expect(each_with_pagename).to be_a(Enumerator)
+ expect(each_with_pagename.to_a.last).to eq([spreadsheet.default_sheet, spreadsheet])
+ end
end
end
@@ -277,7 +289,21 @@ EOS
end
it 'should convert the spreadsheet to csv using the separator when is passed on the parameter' do
- expect(spreadsheet.to_csv(nil, ';')).to eq(expected_csv_with_semicolons)
+ expect(spreadsheet.to_csv(separator: ';')).to eq(expected_csv_with_semicolons)
+ end
+
+ context 'should contains the deprecation warning message' do
+ it 'convert the spreadsheet to csv using the separator' do
+ converting =-> { spreadsheet.to_csv(nil, ';') }
+ expect(converting.call).to eq(expected_csv_with_semicolons)
+ expect(&converting).to output(/DEPRECATION.*:separator\b/).to_stderr
+ end
+
+ it 'be able to arguments: filename, separator, sheet' do
+ converting =-> { spreadsheet.to_csv(nil, ';', spreadsheet.default_sheet) }
+ expect(converting.call).to eq(expected_csv_with_semicolons)
+ expect(&converting).to output(/DEPRECATION.*:sheet\b/).to_stderr
+ end
end
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index a093008..f35cf55 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -6,4 +6,15 @@ RSpec.configure do |c|
c.include Helpers
c.color = true
c.formatter = :documentation if ENV["USE_REPORTERS"]
+ original_stderr = $stderr
+ original_stdout = $stdout
+ c.before(:all) do
+ # Redirect stderr and stdout
+ $stderr = File.open(File::NULL, "w")
+ $stdout = File.open(File::NULL, "w")
+ end
+ c.after(:all) do
+ $stderr = original_stderr
+ $stdout = original_stdout
+ end
end
diff --git a/test/excelx/cell/test_number.rb b/test/excelx/cell/test_number.rb
index ddcffeb..58c9ff7 100644
--- a/test/excelx/cell/test_number.rb
+++ b/test/excelx/cell/test_number.rb
@@ -35,6 +35,11 @@ class TestRooExcelxCellNumber < Minitest::Test
assert_kind_of(Float, cell.value)
end
+ def test_rounded_percent_formatted_value
+ cell = Roo::Excelx::Cell::Number.new '0.569999999995', nil, ['0%'], nil, nil, nil
+ assert_equal('57%', cell.formatted_value)
+ end
+
def test_formats_with_negative_numbers
[
['#,##0 ;(#,##0)', '(1,042)'],
diff --git a/test/files/comments-with-author.xlsx b/test/files/comments-with-author.xlsx
new file mode 100644
index 0000000..6377aaf
--- /dev/null
+++ b/test/files/comments-with-author.xlsx
Binary files differ
diff --git a/test/helpers/test_accessing_files.rb b/test/helpers/test_accessing_files.rb
index 8732bc8..5cccf27 100644
--- a/test/helpers/test_accessing_files.rb
+++ b/test/helpers/test_accessing_files.rb
@@ -36,6 +36,27 @@ module TestAccesingFiles
end
end
+ def test_finalize_twice
+ skip if defined? JRUBY_VERSION
+
+ instance = Class.new { include Roo::Tempdir }.new
+
+ tempdir = instance.make_tempdir(instance, "my_temp_prefix", nil)
+ assert File.exist?(tempdir), "Expected #{tempdir} to initially exist"
+
+ pid = Process.fork do
+ # Inside the forked process finalize does not affect the parent process's state, but does
+ # delete the tempfile on disk
+ instance.finalize_tempdirs(instance.object_id)
+ end
+
+ Process.wait(pid)
+ refute File.exist?(tempdir), "Expected #{tempdir} to have been cleaned up by child process"
+
+ instance.finalize_tempdirs(instance.object_id)
+ refute File.exist?(tempdir), "Expected #{tempdir} to still have been cleaned up"
+ end
+
def test_cleanup_on_error
# NOTE: This test was occasionally failing because when it started running
# other tests would have already added folders to the temp directory,
diff --git a/test/helpers/test_comments.rb b/test/helpers/test_comments.rb
index 2e26786..e204b1a 100644
--- a/test/helpers/test_comments.rb
+++ b/test/helpers/test_comments.rb
@@ -40,4 +40,15 @@ module TestComments
assert_equal expected_comments, oo.comments(oo.sheets.first), "comments error in class #{oo.class}"
end
end
+
+ def test_excel_comment_with_author
+ options = { name: "comments-with-author", format: [:excelx] }
+ expexted_comments = [
+ [6, 2, "Eli Wang:\ncomment with author"]
+ ]
+
+ with_each_spreadsheet(options) do |oo|
+ assert_equal expexted_comments, oo.comments(oo.sheets.first), "comments error in class #{oo.class}"
+ end
+ end
end
diff --git a/test/roo/test_open_office.rb b/test/roo/test_open_office.rb
index 18083a5..897945a 100644
--- a/test/roo/test_open_office.rb
+++ b/test/roo/test_open_office.rb
@@ -224,7 +224,7 @@ class TestRooOpenOffice < Minitest::Test
assert workbook.empty?("C", 1)
assert workbook.empty?("D", 1)
expected = 1
- letter = "e"
+ letter = String.new("e")
while letter <= "u"
assert_equal expected, workbook.cell(letter, 1)
letter.succ!
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 9b761af..2d4fe8f 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -80,7 +80,7 @@ def local_server(port)
end
def start_local_server(filename, port = nil)
- require "rack"
+ require "rackup"
content_type = filename.split(".").last
port ||= TEST_RACK_PORT
@@ -92,7 +92,7 @@ def start_local_server(filename, port = nil)
]
end
- t = Thread.new { Rack::Handler::WEBrick.run web_server, Host: "0.0.0.0", Port: port , Logger: WEBrick::BasicLog.new(nil,1) }
+ t = Thread.new { Rackup::Handler::WEBrick.run web_server, Host: "0.0.0.0", Port: port , Logger: WEBrick::BasicLog.new(nil,1) }
# give the app a chance to startup
sleep(0.2)
diff --git a/test/test_roo.rb b/test/test_roo.rb
index bd1188d..247c947 100644
--- a/test/test_roo.rb
+++ b/test/test_roo.rb
@@ -4,8 +4,6 @@
# with the wrong spreadsheet class
#STDERR.reopen "/dev/null","w"
-Encoding.default_external = "UTF-8"
-
require 'test_helper'
require 'stringio'