[#56965] [ruby-trunk - Bug #8852][Open] Synology build of ruby-2.0.0-p247 is failing — "barbecuesteve (Steve Sparks)" <sparks@...>

12 messages 2013/09/02

[#57051] [ruby-trunk - Bug #8872][Open] Case statements do not honor a refinement of the '===' method — "jconley88 (Jon Conley)" <schnozberries@...>

21 messages 2013/09/07

[#57058] [ruby-trunk - Bug #8875][Open] Select is not usable with SSLSocket — "headius (Charles Nutter)" <headius@...>

11 messages 2013/09/07

[#57074] [ruby-trunk - Bug #8879][Open] String#to_r fails after moving ruby to other OSX system — "mpapis (Michal Papis)" <mpapis@...>

12 messages 2013/09/08

[#57092] [ruby-trunk - Bug #8883][Open] Rational canonicalization unexpectedly converts to Fixnum — "melquiades (Paul Cantrell)" <cantrell@...>

16 messages 2013/09/09

[#57109] [ruby-trunk - Bug #8886][Open] TracePoint API inconsistence when raise used — deivid (David Rodríguez) <deivid.rodriguez@...>

14 messages 2013/09/10

[#57111] [ruby-trunk - Feature #8887][Open] min(n), max(n), min_by(n), max_by(n) — "akr (Akira Tanaka)" <akr@...>

13 messages 2013/09/10

[#57131] [ruby-trunk - Feature #8895][Open] Destructuring Assignment for Hash — "chendo (Jack Chen)" <ruby-lang@...>

19 messages 2013/09/11

[#57186] [ruby-trunk - Feature #8909][Open] Expand "f" frozen suffix to literal arrays and hashes — "headius (Charles Nutter)" <headius@...>

37 messages 2013/09/14

[#57262] [ruby-trunk - Feature #8921][Open] Allow select, reject, etc to accept a regex — "kyledecot (Kyle Decot)" <kyle.decot@...>

13 messages 2013/09/18

[#57273] [ruby-trunk - Feature #8923][Open] Frozen nil/true/false — "ko1 (Koichi Sasada)" <redmine@...>

13 messages 2013/09/19

[#57353] [ruby-trunk - Feature #8948][Open] Frozen regex — "sawa (Tsuyoshi Sawada)" <sawadatsuyoshi@...>

19 messages 2013/09/24

[#57385] [ruby-trunk - Bug #8953][Open] `str =~ /pattern/` does not call =~ method if (1) str is a String, (2) /pattern/ is a Regexp literal — "gfx (Goro Fuji)" <gfuji@...>

12 messages 2013/09/26

[#57396] [ruby-trunk - Feature #8956][Open] Allow hash members delimited by \n inside of {} — "adamdunson (Adam Dunson)" <adam@...>

20 messages 2013/09/26

[ruby-core:57285] [ruby-trunk - Bug #8929] CSV.foreach(filename) without block returns failing Enumerator

From: "martinjos (Martin Sidaway)" <msidaway@...>
Date: 2013-09-19 22:28:20 UTC
List: ruby-core #57285
Issue #8929 has been updated by martinjos (Martin Sidaway).


I can see that it is tricky, because a normal enumerator created by calling CSV#each shouldn't necessarily close the file (as the user may want to call #rewind), but when you use CSV.foreach you have no reference to the CSV object, and you don't want the file handle to be left open.

However, I don't see why, in principle, CSV.foreach(filename) as an Enumerator shouldn't be supported. It has clear, well-defined semantics: it just has to close the file automatically after yielding the last entry.

Also, this would be consistent with, amongst other things, File.foreach(filename).

The present behaviour occurs because self.foreach() uses the block form of self.open(), which ensures the csv object is closed after yielding it. It then calls csv.each(&block) inside the open block, which is okay if a block was passed in to self.foreach, but if not, the no-block form of each() simply calls to_enum (from Object). This enumerator then gets passed out of the open block (becoming invalidated in the process), and out of self.foreach.

In other words:

class CSV

  def self.foreach(path, options = Hash.new, &block)
    open(path, options) do |csv|
      csv.each(&block)
    end
  end

  def self.open(*args)
    (...)
    if block_given?
      begin
        yield csv
      ensure
        csv.close
      end
    else
      csv
    end
  end

  def each
    if block_given?
      while row = shift
        yield row
      end
    else
      to_enum
    end
  end

end

A solution might be to create an alternative version of CSV#each that calls CSV#close after the last entry:

  def each_closing
    if block_given?
      begin
        while row = shift
          yield row
        end
      ensure
        close
      end
    else
      to_enum(__method__)   # __method__ returns :each_closing
    end
  end

Then CSV.foreach could be:

  def self.foreach(path, options = Hash.new, &block)
    if block_given?
      open(path, options) do |csv|
        csv.each(&block)
      end
    else
      open(path, options).each_closing
    end
  end

----------------------------------------
Bug #8929: CSV.foreach(filename) without block returns failing Enumerator
https://bugs.ruby-lang.org/issues/8929#change-41899

Author: martinjos (Martin Sidaway)
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 
ruby -v: 2.0.0-p247
Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN


CSV.foreach(filename) {|entry| p entry }  => works
CSV.foreach(filename).to_a                => fails

It gives the following error:

IOError: closed stream
	from /home/martin/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/csv.rb:1776:in `gets'
	from /home/martin/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/csv.rb:1776:in `block in shift'
	from /home/martin/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/csv.rb:1774:in `loop'
	from /home/martin/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/csv.rb:1774:in `shift'
	from /home/martin/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/csv.rb:1716:in `each'
	from (irb):7:in `each'
	from (irb):7:in `to_a'
        (...)



-- 
http://bugs.ruby-lang.org/

In This Thread