ptools 1.5.0 → 1.5.1
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGES.md +8 -0
- data/Rakefile +1 -0
- data/lib/ptools.rb +37 -36
- data/ptools.gemspec +4 -2
- data/spec/binary_spec.rb +1 -1
- data/spec/constants_spec.rb +1 -1
- data/spec/head_spec.rb +1 -1
- data/spec/tail_spec.rb +1 -1
- data/spec/wc_spec.rb +1 -1
- data/spec/whereis_spec.rb +2 -2
- data/spec/which_spec.rb +5 -5
- data.tar.gz.sig +0 -0
- metadata +5 -6
- metadata.gz.sig +1 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 36d688bdf86ee95a0f1f6d422f75825903fc8ed26d821a69d617134d146a25e3
|
|
4
|
+
data.tar.gz: 574b230aff9a5b095f59cdbb6f1d7b65bc78b27970d4cc2ecc25a1fd67ecbaf0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7a6ede88a24e97f927f6dcc81e9887a0d2b260013fe8e14931796489ec35723d9276651ddcd6ebd6d88cad32f65e0f1298234a0626af95b3b3c0ee157cc1c70a
|
|
7
|
+
data.tar.gz: 4bab6fdf21c8d7f0c3bae158319bb5b2131125d0d757e2d0c24b0d430345b7b7162bcf4b70e44d481c7d7c46aae7b3ead9545f4ad920038023511aa1190dc30d
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGES.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## 1.5.1 - 27-Nov-2025
|
|
2
|
+
* Refactoring release.
|
|
3
|
+
* The wc('all') method now only does a single read instead of a double read.
|
|
4
|
+
* The nl_convert method simplified to use the block form of File.open.
|
|
5
|
+
* More consistent binary encoding calls.
|
|
6
|
+
* Some magic numbers were replaced with constants.
|
|
7
|
+
* Specs run in documentation mode.
|
|
8
|
+
|
|
1
9
|
## 1.5.0 - 5-Dec-2022
|
|
2
10
|
* Change license to Apache-2.0.
|
|
3
11
|
* Altered the File.binary? method. It no longer accepts a second argument,
|
data/Rakefile
CHANGED
data/lib/ptools.rb
CHANGED
|
@@ -3,7 +3,7 @@ require 'win32/file' if File::ALT_SEPARATOR
|
|
|
3
3
|
|
|
4
4
|
class File
|
|
5
5
|
# The version of the ptools library.
|
|
6
|
-
PTOOLS_VERSION = '1.5.
|
|
6
|
+
PTOOLS_VERSION = '1.5.1'.freeze
|
|
7
7
|
|
|
8
8
|
# :stopdoc:
|
|
9
9
|
|
|
@@ -11,7 +11,7 @@ class File
|
|
|
11
11
|
if File::ALT_SEPARATOR
|
|
12
12
|
MSWINDOWS = true
|
|
13
13
|
if ENV['PATHEXT']
|
|
14
|
-
WIN32EXTS = ".{#{ENV['PATHEXT'].tr(';', ',').tr('.', '')}}".downcase
|
|
14
|
+
WIN32EXTS = String.new(".{#{ENV['PATHEXT'].tr(';', ',').tr('.', '')}}").downcase
|
|
15
15
|
else
|
|
16
16
|
WIN32EXTS = '.{exe,com,bat}'.freeze
|
|
17
17
|
end
|
|
@@ -26,6 +26,10 @@ class File
|
|
|
26
26
|
|
|
27
27
|
IMAGE_EXT = %w[.bmp .gif .jpg .jpeg .png .ico].freeze
|
|
28
28
|
|
|
29
|
+
# Constants for file operations
|
|
30
|
+
BLOCK_SIZE = 512
|
|
31
|
+
TAIL_CHUNK_SIZE = 2**16 # 64k chunks
|
|
32
|
+
|
|
29
33
|
# :startdoc:
|
|
30
34
|
|
|
31
35
|
# Returns whether or not the file is an image. Only JPEG, PNG, BMP,
|
|
@@ -90,7 +94,7 @@ class File
|
|
|
90
94
|
# File.which('ruby') # => '/usr/local/bin/ruby'
|
|
91
95
|
# File.which('foo') # => nil
|
|
92
96
|
#
|
|
93
|
-
def self.which(program, path = ENV
|
|
97
|
+
def self.which(program, path = ENV.fetch('PATH', nil))
|
|
94
98
|
raise ArgumentError, 'path cannot be empty' if path.nil? || path.empty?
|
|
95
99
|
|
|
96
100
|
# Bail out early if an absolute path is provided.
|
|
@@ -143,7 +147,7 @@ class File
|
|
|
143
147
|
# File.whereis('ruby') # => ['/usr/bin/ruby', '/usr/local/bin/ruby']
|
|
144
148
|
# File.whereis('foo') # => nil
|
|
145
149
|
#
|
|
146
|
-
def self.whereis(program, path = ENV
|
|
150
|
+
def self.whereis(program, path = ENV.fetch('PATH', nil))
|
|
147
151
|
raise ArgumentError, 'path cannot be empty' if path.nil? || path.empty?
|
|
148
152
|
|
|
149
153
|
paths = []
|
|
@@ -232,13 +236,11 @@ class File
|
|
|
232
236
|
# to be configured in the future as an optional 3rd argument.
|
|
233
237
|
#
|
|
234
238
|
def self.tail(filename, num_lines = 10, &block)
|
|
235
|
-
tail_size = 2**16 # 64k chunks
|
|
236
|
-
|
|
237
239
|
# MS Windows gets unhappy if you try to seek backwards past the
|
|
238
240
|
# end of the file, so we have some extra checks here and later.
|
|
239
241
|
file_size = File.size(filename)
|
|
240
|
-
read_bytes = file_size %
|
|
241
|
-
read_bytes =
|
|
242
|
+
read_bytes = file_size % TAIL_CHUNK_SIZE
|
|
243
|
+
read_bytes = TAIL_CHUNK_SIZE if read_bytes == 0
|
|
242
244
|
|
|
243
245
|
line_sep = File::ALT_SEPARATOR ? "\r\n" : "\n"
|
|
244
246
|
|
|
@@ -252,7 +254,7 @@ class File
|
|
|
252
254
|
while buf.scan(line_sep).size <= num_lines and position >= 0
|
|
253
255
|
fh.seek(position, IO::SEEK_SET)
|
|
254
256
|
buf = fh.read(read_bytes) + buf
|
|
255
|
-
read_bytes =
|
|
257
|
+
read_bytes = TAIL_CHUNK_SIZE
|
|
256
258
|
position -= read_bytes
|
|
257
259
|
end
|
|
258
260
|
end
|
|
@@ -288,24 +290,23 @@ class File
|
|
|
288
290
|
if old_file == new_file
|
|
289
291
|
require 'tempfile'
|
|
290
292
|
temp_name = Time.new.strftime('%Y%m%d%H%M%S')
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
nf.open if old_file == new_file
|
|
298
|
-
File.foreach(old_file) do |line|
|
|
299
|
-
line.chomp!
|
|
300
|
-
nf.print("#{line}#{format}")
|
|
301
|
-
end
|
|
302
|
-
ensure
|
|
303
|
-
nf.close if nf && !nf.closed?
|
|
304
|
-
if old_file == new_file
|
|
293
|
+
Tempfile.open("ruby_temp_#{temp_name}") do |nf|
|
|
294
|
+
File.foreach(old_file) do |line|
|
|
295
|
+
line.chomp!
|
|
296
|
+
nf.print("#{line}#{format}")
|
|
297
|
+
end
|
|
298
|
+
nf.close
|
|
305
299
|
require 'fileutils'
|
|
306
300
|
File.delete(old_file)
|
|
307
301
|
FileUtils.mv(nf.path, old_file)
|
|
308
302
|
end
|
|
303
|
+
else
|
|
304
|
+
File.open(new_file, 'w') do |nf|
|
|
305
|
+
File.foreach(old_file) do |line|
|
|
306
|
+
line.chomp!
|
|
307
|
+
nf.print("#{line}#{format}")
|
|
308
|
+
end
|
|
309
|
+
end
|
|
309
310
|
end
|
|
310
311
|
|
|
311
312
|
self
|
|
@@ -358,13 +359,13 @@ class File
|
|
|
358
359
|
n
|
|
359
360
|
else
|
|
360
361
|
bytes, chars, lines, words = 0, 0, 0, 0
|
|
361
|
-
File.foreach(filename) do |line|
|
|
362
|
-
lines += 1
|
|
363
|
-
words += line.split.length
|
|
364
|
-
chars += line.chars.length
|
|
365
|
-
end
|
|
366
362
|
File.open(filename) do |f|
|
|
367
|
-
|
|
363
|
+
while (line = f.gets)
|
|
364
|
+
lines += 1
|
|
365
|
+
words += line.split.length
|
|
366
|
+
chars += line.chars.length
|
|
367
|
+
bytes += line.bytesize
|
|
368
|
+
end
|
|
368
369
|
end
|
|
369
370
|
[bytes, chars, words, lines]
|
|
370
371
|
end
|
|
@@ -382,7 +383,7 @@ class File
|
|
|
382
383
|
#
|
|
383
384
|
def self.sparse?(file)
|
|
384
385
|
stats = File.stat(file)
|
|
385
|
-
stats.size > stats.blocks *
|
|
386
|
+
stats.size > stats.blocks * BLOCK_SIZE
|
|
386
387
|
end
|
|
387
388
|
end
|
|
388
389
|
|
|
@@ -423,25 +424,25 @@ class File
|
|
|
423
424
|
#
|
|
424
425
|
def self.bmp?(file)
|
|
425
426
|
data = File.read(file, 6, nil, :encoding => 'binary')
|
|
426
|
-
data[0,2] == 'BM' && File.size(file) == data[2,4].
|
|
427
|
+
data[0, 2] == 'BM' && File.size(file) == data[2, 4].unpack1('i')
|
|
427
428
|
end
|
|
428
429
|
|
|
429
430
|
# Is the file a jpeg file?
|
|
430
431
|
#
|
|
431
432
|
def self.jpg?(file)
|
|
432
|
-
File.read(file, 10, nil, :encoding => 'binary') == "\
|
|
433
|
+
File.read(file, 10, nil, :encoding => 'binary') == "\xFF\xD8\xFF\xE0\x00\x10JFIF".force_encoding(Encoding::BINARY)
|
|
433
434
|
end
|
|
434
435
|
|
|
435
436
|
# Is the file a png file?
|
|
436
437
|
#
|
|
437
438
|
def self.png?(file)
|
|
438
|
-
File.read(file, 4, nil, :encoding => 'binary') == "\
|
|
439
|
+
File.read(file, 4, nil, :encoding => 'binary') == "\x89PNG".force_encoding(Encoding::BINARY)
|
|
439
440
|
end
|
|
440
441
|
|
|
441
442
|
# Is the file a gif?
|
|
442
443
|
#
|
|
443
444
|
def self.gif?(file)
|
|
444
|
-
%w[GIF89a GIF97a].include?(File.read(file, 6))
|
|
445
|
+
%w[GIF89a GIF97a].include?(File.read(file, 6, nil, :encoding => 'binary'))
|
|
445
446
|
end
|
|
446
447
|
|
|
447
448
|
# Is the file a tiff?
|
|
@@ -449,7 +450,7 @@ class File
|
|
|
449
450
|
def self.tiff?(file)
|
|
450
451
|
return false if File.size(file) < 12
|
|
451
452
|
|
|
452
|
-
bytes = File.read(file, 4)
|
|
453
|
+
bytes = File.read(file, 4, nil, :encoding => 'binary')
|
|
453
454
|
|
|
454
455
|
# II is Intel, MM is Motorola
|
|
455
456
|
return false if bytes[0..1] != 'II' && bytes[0..1] != 'MM'
|
|
@@ -464,6 +465,6 @@ class File
|
|
|
464
465
|
# Is the file an ico file?
|
|
465
466
|
#
|
|
466
467
|
def self.ico?(file)
|
|
467
|
-
["\
|
|
468
|
+
["\x00\x00\x01\x00".force_encoding(Encoding::BINARY), "\x00\x00\x02\x00".force_encoding(Encoding::BINARY)].include?(File.read(file, 4, nil, :encoding => 'binary'))
|
|
468
469
|
end
|
|
469
470
|
end
|
data/ptools.gemspec
CHANGED
|
@@ -2,7 +2,7 @@ require 'rbconfig'
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |spec|
|
|
4
4
|
spec.name = 'ptools'
|
|
5
|
-
spec.version = '1.5.
|
|
5
|
+
spec.version = '1.5.1'
|
|
6
6
|
spec.license = 'Apache-2.0'
|
|
7
7
|
spec.author = 'Daniel J. Berger'
|
|
8
8
|
spec.email = 'djberg96@gmail.com'
|
|
@@ -25,7 +25,9 @@ Gem::Specification.new do |spec|
|
|
|
25
25
|
'documentation_uri' => 'https://github.com/djberg96/ptools/wiki',
|
|
26
26
|
'source_code_uri' => 'https://github.com/djberg96/ptools',
|
|
27
27
|
'wiki_uri' => 'https://github.com/djberg96/ptools/wiki',
|
|
28
|
-
'rubygems_mfa_required' => 'true'
|
|
28
|
+
'rubygems_mfa_required' => 'true',
|
|
29
|
+
'github_repo' => 'https://github.com/djberg96/ptools',
|
|
30
|
+
'funding_uri' => 'https://github.com/sponsors/djberg96'
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
spec.add_development_dependency('rake')
|
data/spec/binary_spec.rb
CHANGED
|
@@ -10,7 +10,7 @@ require 'ptools'
|
|
|
10
10
|
|
|
11
11
|
RSpec.describe File, :binary do
|
|
12
12
|
let(:dirname) { described_class.dirname(__FILE__) }
|
|
13
|
-
let(:bin_file) { File::ALT_SEPARATOR ? described_class.join(ENV
|
|
13
|
+
let(:bin_file) { File::ALT_SEPARATOR ? described_class.join(ENV.fetch('windir', nil), 'notepad.exe') : '/bin/ls' }
|
|
14
14
|
|
|
15
15
|
before do
|
|
16
16
|
@txt_file = described_class.join(dirname, 'txt', 'english.txt')
|
data/spec/constants_spec.rb
CHANGED
|
@@ -13,7 +13,7 @@ RSpec.describe File, :constants do
|
|
|
13
13
|
let(:windows) { File::ALT_SEPARATOR }
|
|
14
14
|
|
|
15
15
|
example 'PTOOLS_VERSION constant is set to expected value' do
|
|
16
|
-
expect(File::PTOOLS_VERSION).to eq('1.5.
|
|
16
|
+
expect(File::PTOOLS_VERSION).to eq('1.5.1')
|
|
17
17
|
expect(File::PTOOLS_VERSION.frozen?).to be true
|
|
18
18
|
end
|
|
19
19
|
|
data/spec/head_spec.rb
CHANGED
|
@@ -29,7 +29,7 @@ RSpec.describe File, :head do
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
example 'head method returns the expected results' do
|
|
32
|
-
expect(described_class.head(test_file)).to
|
|
32
|
+
expect(described_class.head(test_file)).to be_a(Array)
|
|
33
33
|
expect(described_class.head(test_file)).to eq(@expected_head1)
|
|
34
34
|
expect(described_class.head(test_file, 5)).to eq(@expected_head2)
|
|
35
35
|
end
|
data/spec/tail_spec.rb
CHANGED
|
@@ -74,7 +74,7 @@ RSpec.describe File, :tail do
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
example 'tail returns the expected values' do
|
|
77
|
-
expect(described_class.tail(test_file1)).to
|
|
77
|
+
expect(described_class.tail(test_file1)).to be_a(Array)
|
|
78
78
|
expect(described_class.tail(test_file1)).to eq(@expected_tail1)
|
|
79
79
|
expect(described_class.tail(test_file1, 5)).to eq(@expected_tail2)
|
|
80
80
|
end
|
data/spec/wc_spec.rb
CHANGED
|
@@ -35,7 +35,7 @@ RSpec.describe File, :wc do
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
example 'wc with no option returns expected results' do
|
|
38
|
-
expect(described_class.wc(test_file)).to
|
|
38
|
+
expect(described_class.wc(test_file)).to be_a(Array)
|
|
39
39
|
expect(described_class.wc(test_file)).to eq([166, 166, 25, 25])
|
|
40
40
|
end
|
|
41
41
|
|
data/spec/whereis_spec.rb
CHANGED
|
@@ -34,7 +34,7 @@ RSpec.describe File, :whereis do
|
|
|
34
34
|
example 'whereis basic functionality' do
|
|
35
35
|
expect(described_class).to respond_to(:whereis)
|
|
36
36
|
expect{ described_class.whereis('ruby') }.not_to raise_error
|
|
37
|
-
expect(described_class.whereis('ruby')).to
|
|
37
|
+
expect(described_class.whereis('ruby')).to be_a(Array).or be_nil
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
example 'whereis accepts an optional second argument' do
|
|
@@ -43,7 +43,7 @@ RSpec.describe File, :whereis do
|
|
|
43
43
|
|
|
44
44
|
example 'whereis returns expected values' do
|
|
45
45
|
expect{ @actual_locs = described_class.whereis(ruby) }.not_to raise_error
|
|
46
|
-
expect(@actual_locs).to
|
|
46
|
+
expect(@actual_locs).to be_a(Array)
|
|
47
47
|
expect((@expected_locs & @actual_locs).size > 0).to be true
|
|
48
48
|
end
|
|
49
49
|
|
data/spec/which_spec.rb
CHANGED
|
@@ -18,8 +18,8 @@ describe File, :which do
|
|
|
18
18
|
|
|
19
19
|
Dir.mkdir(@dir) unless described_class.exist?(@dir)
|
|
20
20
|
FileUtils.touch(@non_exe)
|
|
21
|
-
described_class.chmod(
|
|
22
|
-
described_class.chmod(
|
|
21
|
+
described_class.chmod(0775, @dir)
|
|
22
|
+
described_class.chmod(0644, @non_exe)
|
|
23
23
|
|
|
24
24
|
@exe = described_class.join(
|
|
25
25
|
RbConfig::CONFIG['bindir'],
|
|
@@ -40,7 +40,7 @@ describe File, :which do
|
|
|
40
40
|
example 'which method basic functionality' do
|
|
41
41
|
expect(described_class).to respond_to(:which)
|
|
42
42
|
expect{ described_class.which(@ruby) }.not_to raise_error
|
|
43
|
-
expect(described_class.which(@ruby)).to
|
|
43
|
+
expect(described_class.which(@ruby)).to be_a(String)
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
example 'which accepts an optional path to search' do
|
|
@@ -92,10 +92,10 @@ describe File, :which do
|
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
example 'resolves with with ~', :unix_only => true do
|
|
95
|
-
old_home =
|
|
95
|
+
old_home = Dir.home
|
|
96
96
|
ENV['HOME'] = Dir::Tmpname.tmpdir
|
|
97
97
|
program = Tempfile.new(['program', '.sh'])
|
|
98
|
-
described_class.chmod(
|
|
98
|
+
described_class.chmod(0755, program.path)
|
|
99
99
|
|
|
100
100
|
expect(described_class.which(described_class.basename(program.path), '~/')).not_to be_nil
|
|
101
101
|
ensure
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ptools
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.5.
|
|
4
|
+
version: 1.5.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel J. Berger
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain:
|
|
11
10
|
- |
|
|
@@ -35,7 +34,7 @@ cert_chain:
|
|
|
35
34
|
ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
|
|
36
35
|
WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
|
|
37
36
|
-----END CERTIFICATE-----
|
|
38
|
-
date:
|
|
37
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
39
38
|
dependencies:
|
|
40
39
|
- !ruby/object:Gem::Dependency
|
|
41
40
|
name: rake
|
|
@@ -145,7 +144,8 @@ metadata:
|
|
|
145
144
|
source_code_uri: https://github.com/djberg96/ptools
|
|
146
145
|
wiki_uri: https://github.com/djberg96/ptools/wiki
|
|
147
146
|
rubygems_mfa_required: 'true'
|
|
148
|
-
|
|
147
|
+
github_repo: https://github.com/djberg96/ptools
|
|
148
|
+
funding_uri: https://github.com/sponsors/djberg96
|
|
149
149
|
rdoc_options: []
|
|
150
150
|
require_paths:
|
|
151
151
|
- lib
|
|
@@ -160,8 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
160
160
|
- !ruby/object:Gem::Version
|
|
161
161
|
version: '0'
|
|
162
162
|
requirements: []
|
|
163
|
-
rubygems_version: 3.
|
|
164
|
-
signing_key:
|
|
163
|
+
rubygems_version: 3.6.9
|
|
165
164
|
specification_version: 4
|
|
166
165
|
summary: Extra methods for the File class
|
|
167
166
|
test_files: []
|
metadata.gz.sig
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
�������v� �k>���N�R'7��QaO�Y��#�D���@� 0w�J4�R����4�>�F��]#�d�}�h��s�Kģ���!?���9�E��ʟDD
|
|
1
|
+
AՇK����p�֑HH]C��Q�m�,hL��e;�ҟ�zƱS�qѶ�[�X���S���WD�sg��NUXm�2��?rDx�&o=�9��a�*X0�8Ӏ��Aml���磰k$5o�S�S���NZ���c+X͙��j�3�=���I{���_�`W���i�r�Qb���* ��i=�r���Y�
|