tempfile 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6ccc754d48cea474a69828abfd078e10caca47c832b2f9ff8d21f9a64f1e0f22
4
+ data.tar.gz: 2ee1ed2819d49208a4501c1a5e4ecc25707e2d53e331696b9f7d0fb460d30538
5
+ SHA512:
6
+ metadata.gz: e7b403c598ec72689933ffab89f635e28a61029cc421852b842a064aa92d2ef863cc67b83535bec4b70ef483add54b02460d5b540a1ab8427e6d86196669e4df
7
+ data.tar.gz: 12536bd046614d957e368353c27cc4961f86ca6b404963aa1ebd094377055404c1c31dc09fff99124bc7ae151888118dfecdd9eb205e11fe57696cf11cde8598
@@ -0,0 +1,24 @@
1
+ name: ubuntu
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ name: build (${{ matrix.ruby }} / ${{ matrix.os }})
8
+ strategy:
9
+ matrix:
10
+ ruby: [ 2.7, 2.6, 2.5, head ]
11
+ os: [ ubuntu-latest, macos-latest ]
12
+ runs-on: ${{ matrix.os }}
13
+ steps:
14
+ - uses: actions/checkout@master
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: ${{ matrix.ruby }}
19
+ - name: Install dependencies
20
+ run: |
21
+ gem install bundler --no-document
22
+ bundle install
23
+ - name: Run test
24
+ run: rake test
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "rake"
6
+ gem "test-unit"
@@ -0,0 +1,23 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tempfile (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ power_assert (1.1.5)
10
+ rake (13.0.1)
11
+ test-unit (3.3.5)
12
+ power_assert
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ rake
19
+ tempfile!
20
+ test-unit
21
+
22
+ BUNDLED WITH
23
+ 2.1.4
@@ -0,0 +1,51 @@
1
+ # Tempfile
2
+
3
+ A utility class for managing temporary files. When you create a Tempfile
4
+ object, it will create a temporary file with a unique filename. A Tempfile
5
+ objects behaves just like a File object, and you can perform all the usual
6
+ file operations on it: reading data, writing data, changing its permissions,
7
+ etc. So although this class does not explicitly document all instance methods
8
+ supported by File, you can in fact call any File instance method on a
9
+ Tempfile object.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'tempfile'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle install
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install tempfile
26
+
27
+ ## Usage
28
+
29
+ ```ruby
30
+ require 'tempfile'
31
+
32
+ file = Tempfile.new('foo')
33
+ file.path # => A unique filename in the OS's temp directory,
34
+ # e.g.: "/tmp/foo.24722.0"
35
+ # This filename contains 'foo' in its basename.
36
+ file.write("hello world")
37
+ file.rewind
38
+ file.read # => "hello world"
39
+ file.close
40
+ file.unlink # deletes the temp file
41
+ ```
42
+
43
+ ## Development
44
+
45
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
46
+
47
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
48
+
49
+ ## Contributing
50
+
51
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/tempfile.
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test/lib"
6
+ t.ruby_opts << "-rhelper"
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "tempfile"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,350 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # tempfile - manipulates temporary files
4
+ #
5
+ # $Id$
6
+ #
7
+
8
+ require 'delegate'
9
+ require 'tmpdir'
10
+
11
+ # A utility class for managing temporary files. When you create a Tempfile
12
+ # object, it will create a temporary file with a unique filename. A Tempfile
13
+ # objects behaves just like a File object, and you can perform all the usual
14
+ # file operations on it: reading data, writing data, changing its permissions,
15
+ # etc. So although this class does not explicitly document all instance methods
16
+ # supported by File, you can in fact call any File instance method on a
17
+ # Tempfile object.
18
+ #
19
+ # == Synopsis
20
+ #
21
+ # require 'tempfile'
22
+ #
23
+ # file = Tempfile.new('foo')
24
+ # file.path # => A unique filename in the OS's temp directory,
25
+ # # e.g.: "/tmp/foo.24722.0"
26
+ # # This filename contains 'foo' in its basename.
27
+ # file.write("hello world")
28
+ # file.rewind
29
+ # file.read # => "hello world"
30
+ # file.close
31
+ # file.unlink # deletes the temp file
32
+ #
33
+ # == Good practices
34
+ #
35
+ # === Explicit close
36
+ #
37
+ # When a Tempfile object is garbage collected, or when the Ruby interpreter
38
+ # exits, its associated temporary file is automatically deleted. This means
39
+ # that's it's unnecessary to explicitly delete a Tempfile after use, though
40
+ # it's good practice to do so: not explicitly deleting unused Tempfiles can
41
+ # potentially leave behind large amounts of tempfiles on the filesystem
42
+ # until they're garbage collected. The existence of these temp files can make
43
+ # it harder to determine a new Tempfile filename.
44
+ #
45
+ # Therefore, one should always call #unlink or close in an ensure block, like
46
+ # this:
47
+ #
48
+ # file = Tempfile.new('foo')
49
+ # begin
50
+ # # ...do something with file...
51
+ # ensure
52
+ # file.close
53
+ # file.unlink # deletes the temp file
54
+ # end
55
+ #
56
+ # === Unlink after creation
57
+ #
58
+ # On POSIX systems, it's possible to unlink a file right after creating it,
59
+ # and before closing it. This removes the filesystem entry without closing
60
+ # the file handle, so it ensures that only the processes that already had
61
+ # the file handle open can access the file's contents. It's strongly
62
+ # recommended that you do this if you do not want any other processes to
63
+ # be able to read from or write to the Tempfile, and you do not need to
64
+ # know the Tempfile's filename either.
65
+ #
66
+ # For example, a practical use case for unlink-after-creation would be this:
67
+ # you need a large byte buffer that's too large to comfortably fit in RAM,
68
+ # e.g. when you're writing a web server and you want to buffer the client's
69
+ # file upload data.
70
+ #
71
+ # Please refer to #unlink for more information and a code example.
72
+ #
73
+ # == Minor notes
74
+ #
75
+ # Tempfile's filename picking method is both thread-safe and inter-process-safe:
76
+ # it guarantees that no other threads or processes will pick the same filename.
77
+ #
78
+ # Tempfile itself however may not be entirely thread-safe. If you access the
79
+ # same Tempfile object from multiple threads then you should protect it with a
80
+ # mutex.
81
+ class Tempfile < DelegateClass(File)
82
+ # Creates a temporary file with permissions 0600 (= only readable and
83
+ # writable by the owner) and opens it with mode "w+".
84
+ #
85
+ # The +basename+ parameter is used to determine the name of the
86
+ # temporary file. You can either pass a String or an Array with
87
+ # 2 String elements. In the former form, the temporary file's base
88
+ # name will begin with the given string. In the latter form,
89
+ # the temporary file's base name will begin with the array's first
90
+ # element, and end with the second element. For example:
91
+ #
92
+ # file = Tempfile.new('hello')
93
+ # file.path # => something like: "/tmp/hello2843-8392-92849382--0"
94
+ #
95
+ # # Use the Array form to enforce an extension in the filename:
96
+ # file = Tempfile.new(['hello', '.jpg'])
97
+ # file.path # => something like: "/tmp/hello2843-8392-92849382--0.jpg"
98
+ #
99
+ # The temporary file will be placed in the directory as specified
100
+ # by the +tmpdir+ parameter. By default, this is +Dir.tmpdir+.
101
+ #
102
+ # file = Tempfile.new('hello', '/home/aisaka')
103
+ # file.path # => something like: "/home/aisaka/hello2843-8392-92849382--0"
104
+ #
105
+ # You can also pass an options hash. Under the hood, Tempfile creates
106
+ # the temporary file using +File.open+. These options will be passed to
107
+ # +File.open+. This is mostly useful for specifying encoding
108
+ # options, e.g.:
109
+ #
110
+ # Tempfile.new('hello', '/home/aisaka', encoding: 'ascii-8bit')
111
+ #
112
+ # # You can also omit the 'tmpdir' parameter:
113
+ # Tempfile.new('hello', encoding: 'ascii-8bit')
114
+ #
115
+ # Note: +mode+ keyword argument, as accepted by Tempfile, can only be
116
+ # numeric, combination of the modes defined in File::Constants.
117
+ #
118
+ # === Exceptions
119
+ #
120
+ # If Tempfile.new cannot find a unique filename within a limited
121
+ # number of tries, then it will raise an exception.
122
+ def initialize(basename="", tmpdir=nil, mode: 0, **options)
123
+ warn "Tempfile.new doesn't call the given block.", uplevel: 1 if block_given?
124
+
125
+ @unlinked = false
126
+ @mode = mode|File::RDWR|File::CREAT|File::EXCL
127
+ ::Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
128
+ opts[:perm] = 0600
129
+ @tmpfile = File.open(tmpname, @mode, **opts)
130
+ @opts = opts.freeze
131
+ end
132
+ ObjectSpace.define_finalizer(self, Remover.new(@tmpfile))
133
+
134
+ super(@tmpfile)
135
+ end
136
+
137
+ # Opens or reopens the file with mode "r+".
138
+ def open
139
+ _close
140
+ mode = @mode & ~(File::CREAT|File::EXCL)
141
+ @tmpfile = File.open(@tmpfile.path, mode, **@opts)
142
+ __setobj__(@tmpfile)
143
+ end
144
+
145
+ def _close # :nodoc:
146
+ @tmpfile.close
147
+ end
148
+ protected :_close
149
+
150
+ # Closes the file. If +unlink_now+ is true, then the file will be unlinked
151
+ # (deleted) after closing. Of course, you can choose to later call #unlink
152
+ # if you do not unlink it now.
153
+ #
154
+ # If you don't explicitly unlink the temporary file, the removal
155
+ # will be delayed until the object is finalized.
156
+ def close(unlink_now=false)
157
+ _close
158
+ unlink if unlink_now
159
+ end
160
+
161
+ # Closes and unlinks (deletes) the file. Has the same effect as called
162
+ # <tt>close(true)</tt>.
163
+ def close!
164
+ close(true)
165
+ end
166
+
167
+ # Unlinks (deletes) the file from the filesystem. One should always unlink
168
+ # the file after using it, as is explained in the "Explicit close" good
169
+ # practice section in the Tempfile overview:
170
+ #
171
+ # file = Tempfile.new('foo')
172
+ # begin
173
+ # # ...do something with file...
174
+ # ensure
175
+ # file.close
176
+ # file.unlink # deletes the temp file
177
+ # end
178
+ #
179
+ # === Unlink-before-close
180
+ #
181
+ # On POSIX systems it's possible to unlink a file before closing it. This
182
+ # practice is explained in detail in the Tempfile overview (section
183
+ # "Unlink after creation"); please refer there for more information.
184
+ #
185
+ # However, unlink-before-close may not be supported on non-POSIX operating
186
+ # systems. Microsoft Windows is the most notable case: unlinking a non-closed
187
+ # file will result in an error, which this method will silently ignore. If
188
+ # you want to practice unlink-before-close whenever possible, then you should
189
+ # write code like this:
190
+ #
191
+ # file = Tempfile.new('foo')
192
+ # file.unlink # On Windows this silently fails.
193
+ # begin
194
+ # # ... do something with file ...
195
+ # ensure
196
+ # file.close! # Closes the file handle. If the file wasn't unlinked
197
+ # # because #unlink failed, then this method will attempt
198
+ # # to do so again.
199
+ # end
200
+ def unlink
201
+ return if @unlinked
202
+ begin
203
+ File.unlink(@tmpfile.path)
204
+ rescue Errno::ENOENT
205
+ rescue Errno::EACCES
206
+ # may not be able to unlink on Windows; just ignore
207
+ return
208
+ end
209
+ ObjectSpace.undefine_finalizer(self)
210
+ @unlinked = true
211
+ end
212
+ alias delete unlink
213
+
214
+ # Returns the full path name of the temporary file.
215
+ # This will be nil if #unlink has been called.
216
+ def path
217
+ @unlinked ? nil : @tmpfile.path
218
+ end
219
+
220
+ # Returns the size of the temporary file. As a side effect, the IO
221
+ # buffer is flushed before determining the size.
222
+ def size
223
+ if !@tmpfile.closed?
224
+ @tmpfile.size # File#size calls rb_io_flush_raw()
225
+ else
226
+ File.size(@tmpfile.path)
227
+ end
228
+ end
229
+ alias length size
230
+
231
+ # :stopdoc:
232
+ def inspect
233
+ if @tmpfile.closed?
234
+ "#<#{self.class}:#{path} (closed)>"
235
+ else
236
+ "#<#{self.class}:#{path}>"
237
+ end
238
+ end
239
+
240
+ class Remover # :nodoc:
241
+ def initialize(tmpfile)
242
+ @pid = Process.pid
243
+ @tmpfile = tmpfile
244
+ end
245
+
246
+ def call(*args)
247
+ return if @pid != Process.pid
248
+
249
+ $stderr.puts "removing #{@tmpfile.path}..." if $DEBUG
250
+
251
+ @tmpfile.close
252
+ begin
253
+ File.unlink(@tmpfile.path)
254
+ rescue Errno::ENOENT
255
+ end
256
+
257
+ $stderr.puts "done" if $DEBUG
258
+ end
259
+ end
260
+
261
+ class << self
262
+ # :startdoc:
263
+
264
+ # Creates a new Tempfile.
265
+ #
266
+ # If no block is given, this is a synonym for Tempfile.new.
267
+ #
268
+ # If a block is given, then a Tempfile object will be constructed,
269
+ # and the block is run with said object as argument. The Tempfile
270
+ # object will be automatically closed after the block terminates.
271
+ # The call returns the value of the block.
272
+ #
273
+ # In any case, all arguments (<code>*args</code>) will be passed to Tempfile.new.
274
+ #
275
+ # Tempfile.open('foo', '/home/temp') do |f|
276
+ # # ... do something with f ...
277
+ # end
278
+ #
279
+ # # Equivalent:
280
+ # f = Tempfile.open('foo', '/home/temp')
281
+ # begin
282
+ # # ... do something with f ...
283
+ # ensure
284
+ # f.close
285
+ # end
286
+ def open(*args, **kw)
287
+ tempfile = new(*args, **kw)
288
+
289
+ if block_given?
290
+ begin
291
+ yield(tempfile)
292
+ ensure
293
+ tempfile.close
294
+ end
295
+ else
296
+ tempfile
297
+ end
298
+ end
299
+ end
300
+ end
301
+
302
+ # Creates a temporary file as usual File object (not Tempfile).
303
+ # It doesn't use finalizer and delegation.
304
+ #
305
+ # If no block is given, this is similar to Tempfile.new except
306
+ # creating File instead of Tempfile.
307
+ # The created file is not removed automatically.
308
+ # You should use File.unlink to remove it.
309
+ #
310
+ # If a block is given, then a File object will be constructed,
311
+ # and the block is invoked with the object as the argument.
312
+ # The File object will be automatically closed and
313
+ # the temporary file is removed after the block terminates.
314
+ # The call returns the value of the block.
315
+ #
316
+ # In any case, all arguments (+basename+, +tmpdir+, +mode+, and
317
+ # <code>**options</code>) will be treated as Tempfile.new.
318
+ #
319
+ # Tempfile.create('foo', '/home/temp') do |f|
320
+ # # ... do something with f ...
321
+ # end
322
+ #
323
+ def Tempfile.create(basename="", tmpdir=nil, mode: 0, **options)
324
+ tmpfile = nil
325
+ Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
326
+ mode |= File::RDWR|File::CREAT|File::EXCL
327
+ opts[:perm] = 0600
328
+ tmpfile = File.open(tmpname, mode, **opts)
329
+ end
330
+ if block_given?
331
+ begin
332
+ yield tmpfile
333
+ ensure
334
+ unless tmpfile.closed?
335
+ if File.identical?(tmpfile, tmpfile.path)
336
+ unlinked = File.unlink tmpfile.path rescue nil
337
+ end
338
+ tmpfile.close
339
+ end
340
+ unless unlinked
341
+ begin
342
+ File.unlink tmpfile.path
343
+ rescue Errno::ENOENT
344
+ end
345
+ end
346
+ end
347
+ else
348
+ tmpfile
349
+ end
350
+ end
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "tempfile"
3
+ spec.version = "0.1.0"
4
+ spec.authors = ["Yukihiro Matsumoto"]
5
+ spec.email = ["matz@ruby-lang.org"]
6
+
7
+ spec.summary = %q{A utility class for managing temporary files.}
8
+ spec.description = %q{A utility class for managing temporary files.}
9
+ spec.homepage = "https://github.com/ruby/tempfile"
10
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
11
+
12
+ spec.metadata["homepage_uri"] = spec.homepage
13
+ spec.metadata["source_code_uri"] = spec.homepage
14
+
15
+ # Specify which files should be added to the gem when it is released.
16
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tempfile
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yukihiro Matsumoto
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-04-01 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A utility class for managing temporary files.
14
+ email:
15
+ - matz@ruby-lang.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".github/workflows/test.yml"
21
+ - ".gitignore"
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - README.md
25
+ - Rakefile
26
+ - bin/console
27
+ - bin/setup
28
+ - lib/tempfile.rb
29
+ - tempfile.gemspec
30
+ homepage: https://github.com/ruby/tempfile
31
+ licenses: []
32
+ metadata:
33
+ homepage_uri: https://github.com/ruby/tempfile
34
+ source_code_uri: https://github.com/ruby/tempfile
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 2.5.0
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubygems_version: 3.2.0.pre1
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: A utility class for managing temporary files.
54
+ test_files: []