pixar-ruby-extensions 1.11.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 +7 -0
- data/LICENSE.txt +177 -0
- data/README.md +29 -0
- data/lib/pixar-ruby-extensions.rb +10 -0
- data/lib/pixar_ruby_extensions/array/predicates.rb +30 -0
- data/lib/pixar_ruby_extensions/array/utils.rb +88 -0
- data/lib/pixar_ruby_extensions/array.rb +17 -0
- data/lib/pixar_ruby_extensions/filetest/predicates.rb +38 -0
- data/lib/pixar_ruby_extensions/filetest.rb +14 -0
- data/lib/pixar_ruby_extensions/float/utils.rb +36 -0
- data/lib/pixar_ruby_extensions/float.rb +14 -0
- data/lib/pixar_ruby_extensions/hash/utils.rb +94 -0
- data/lib/pixar_ruby_extensions/hash.rb +15 -0
- data/lib/pixar_ruby_extensions/integer/utils.rb +187 -0
- data/lib/pixar_ruby_extensions/integer.rb +14 -0
- data/lib/pixar_ruby_extensions/ipaddr/predicates.rb +50 -0
- data/lib/pixar_ruby_extensions/ipaddr/utils.rb +77 -0
- data/lib/pixar_ruby_extensions/ipaddr.rb +20 -0
- data/lib/pixar_ruby_extensions/json/jsonl.rb +50 -0
- data/lib/pixar_ruby_extensions/json/utils.rb +78 -0
- data/lib/pixar_ruby_extensions/json.rb +17 -0
- data/lib/pixar_ruby_extensions/object/predicates.rb +49 -0
- data/lib/pixar_ruby_extensions/object.rb +15 -0
- data/lib/pixar_ruby_extensions/pathname/predicates.rb +38 -0
- data/lib/pixar_ruby_extensions/pathname/utils.rb +139 -0
- data/lib/pixar_ruby_extensions/pathname.rb +18 -0
- data/lib/pixar_ruby_extensions/string/conversions.rb +113 -0
- data/lib/pixar_ruby_extensions/string/predicates.rb +52 -0
- data/lib/pixar_ruby_extensions/string.rb +17 -0
- data/lib/pixar_ruby_extensions/time/utils.rb +46 -0
- data/lib/pixar_ruby_extensions/time.rb +16 -0
- data/lib/pixar_ruby_extensions/version.rb +15 -0
- data/lib/pixar_ruby_extensions.rb +44 -0
- metadata +78 -0
@@ -0,0 +1,187 @@
|
|
1
|
+
# Copyright 2025 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
4
|
+
# at the root of this project.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PixarRubyExtensions
|
9
|
+
|
10
|
+
module IntegerExtensions
|
11
|
+
|
12
|
+
module Utils
|
13
|
+
|
14
|
+
# Array for processing pix_humanize_secs.
|
15
|
+
# How many weeks in a year??
|
16
|
+
# first, given the Gregorian calendar, how many days in 1000 years?
|
17
|
+
# 365000 days if all are common years
|
18
|
+
# +250 cuz every 4th year is a leap year
|
19
|
+
# - 7 cuz centuries are only leap years if divisble by 400
|
20
|
+
# so there are only 3, not 10
|
21
|
+
# = 365243
|
22
|
+
#
|
23
|
+
# and there are 7 days per week, so in 1000 years, a week averages to
|
24
|
+
# 365243 / 7
|
25
|
+
# = 5217.7571428571426 weeks per 1000 years
|
26
|
+
# = 52.177571428571426 weeks per year
|
27
|
+
|
28
|
+
HUMANIZE_SECS_ARRAY = [
|
29
|
+
[60, :seconds, :second],
|
30
|
+
[60, :minutes, :minute],
|
31
|
+
[24, :hours, :hour],
|
32
|
+
[7, :days, :day],
|
33
|
+
[52.1776, :weeks, :week],
|
34
|
+
[100, :years, :year],
|
35
|
+
[10, :centuries, :century],
|
36
|
+
[Float::INFINITY, :millenia, :millenium]
|
37
|
+
].freeze
|
38
|
+
|
39
|
+
# Very handy!
|
40
|
+
# Converts an integer number of seconds into a English string, like so:
|
41
|
+
#
|
42
|
+
# 123456789.humanize_secs
|
43
|
+
# # => "3 years 47 weeks 0 days 21 hours 33 minutes 9 seconds"
|
44
|
+
#
|
45
|
+
# Idea credits to:
|
46
|
+
# Mladen Jablanović at
|
47
|
+
# http://stackoverflow.com/questions/4136248/how-to-generate-a-human-readable-time-range-using-ruby-on-rails
|
48
|
+
#
|
49
|
+
# And:
|
50
|
+
# Jonathan Simmons at
|
51
|
+
# https://gist.github.com/jonathansimmons/24fa43ac6ee53819fb93
|
52
|
+
#
|
53
|
+
# @param omit_zeros [Boolean] If true, units with a value of zero, like '0 weeks' or
|
54
|
+
# '0 hours' will be omitted, so the output of calling this on the 123456789 example above
|
55
|
+
# would be "3 years 47 weeks 21 hours 33 minutes 9 seconds". Default is false
|
56
|
+
#
|
57
|
+
# @param down_to [Symbol] One of :seconds, :minutes, :hours, :days, :weeks, :years,
|
58
|
+
# :centuries, :millenia
|
59
|
+
# Only include time units down-to and including this one. Default is :seconds
|
60
|
+
# NOTE: output is truncated not rounded. In the example here, you lose all info
|
61
|
+
# about the 21 hrs, 33 min, and 9 secs, and just see '0 days'
|
62
|
+
# @example:
|
63
|
+
# 123456789.pix_humanize_secs
|
64
|
+
# # => "3 years 47 weeks 0 days 21 hours 33 minutes 9 seconds"
|
65
|
+
#
|
66
|
+
# 123456789.pix_humanize_secs down_to: :days
|
67
|
+
# # => "3 years 47 weeks 0 days"
|
68
|
+
#
|
69
|
+
# @param up_to [Symbol] One of :seconds, :minutes, :hours, :days, :weeks, :years,
|
70
|
+
# :centuries, :millenia
|
71
|
+
# Only include time units up-to and including this one. Default is :years.
|
72
|
+
# @example:
|
73
|
+
# 44567789123.pix_humanize_secs
|
74
|
+
# # => "1412 years 13 weeks 0 days 21 hours 25 minutes 23 seconds"
|
75
|
+
#
|
76
|
+
# 44567789123.pix_humanize_secs up_to: :millenia
|
77
|
+
# # => "1 millenium 4 centuries 12 years 13 weeks 0 days 21 hours 25 minutes 23 seconds"
|
78
|
+
#
|
79
|
+
# @return [String] The integer number of seconds, expressed in descending English time units
|
80
|
+
#
|
81
|
+
def pix_humanize_secs(omit_zeros: false, down_to: :seconds, up_to: :years, fraction: nil)
|
82
|
+
# initialize values for our loop
|
83
|
+
remaining_next_unit = self
|
84
|
+
down_to_this_unit = false
|
85
|
+
up_to_this_unit = false
|
86
|
+
|
87
|
+
output_array = HUMANIZE_SECS_ARRAY.map do |count, current_unit, singular|
|
88
|
+
unit_names = [current_unit, singular]
|
89
|
+
# puts "START: starting next unit: #{current_unit}, remaining_next_unit: #{remaining_next_unit}"
|
90
|
+
|
91
|
+
# stop when or integer hits zero
|
92
|
+
next unless remaining_next_unit.positive?
|
93
|
+
|
94
|
+
# stop if we've hit our up_to unit
|
95
|
+
next if up_to_this_unit
|
96
|
+
|
97
|
+
if unit_names.include?(up_to)
|
98
|
+
up_to_this_unit = true
|
99
|
+
current_unit_count = remaining_next_unit
|
100
|
+
else
|
101
|
+
remaining_next_unit, current_unit_count = remaining_next_unit.divmod(count)
|
102
|
+
end
|
103
|
+
|
104
|
+
# puts "MID: current_unit: #{current_unit}, current_unit_count: #{current_unit_count}, remaining_next_unit: #{remaining_next_unit}"
|
105
|
+
|
106
|
+
# skip if we are below our down_to unit
|
107
|
+
down_to_this_unit ||= unit_names.include?(down_to)
|
108
|
+
next unless down_to_this_unit
|
109
|
+
|
110
|
+
display_current_unit_count = current_unit_count.to_i
|
111
|
+
# if we are processing 'seconds' and there is a fraction, append it to the seconds
|
112
|
+
display_current_unit_count += "0.#{fraction}".to_f if current_unit == :seconds && fraction
|
113
|
+
|
114
|
+
next if omit_zeros && display_current_unit_count.zero?
|
115
|
+
|
116
|
+
display_name = display_current_unit_count == 1 ? singular : current_unit
|
117
|
+
|
118
|
+
"#{display_current_unit_count} #{display_name}"
|
119
|
+
end # map
|
120
|
+
|
121
|
+
output_array.compact.reverse.join ' '
|
122
|
+
end
|
123
|
+
|
124
|
+
A_BYTE = 1
|
125
|
+
B_BYTES = 1.0
|
126
|
+
KB_BYTES = B_BYTES * 1024
|
127
|
+
MB_BYTES = KB_BYTES * 1024
|
128
|
+
GB_BYTES = MB_BYTES * 1024
|
129
|
+
TB_BYTES = GB_BYTES * 1024
|
130
|
+
PB_BYTES = TB_BYTES * 1024
|
131
|
+
|
132
|
+
HUMANIZED_BYTE_UNITS = {
|
133
|
+
A_BYTE => 'byte',
|
134
|
+
B_BYTES => 'bytes',
|
135
|
+
KB_BYTES => 'KiB',
|
136
|
+
MB_BYTES => 'MiB',
|
137
|
+
GB_BYTES => 'GiB',
|
138
|
+
TB_BYTES => 'TiB',
|
139
|
+
PB_BYTES => 'PiB'
|
140
|
+
}.freeze
|
141
|
+
|
142
|
+
# A number of bytes converted into a string showing
|
143
|
+
# KibiBytes, Mebibytes, etc up to Pebibytes, with 2
|
144
|
+
# decimal places of precision.
|
145
|
+
#
|
146
|
+
# Returns a string with the unit in the form 'MiB'
|
147
|
+
# unless < 1KiB, in which case 'byte(s)'
|
148
|
+
# For 76253886 bytes this will return "72.72 MiB"
|
149
|
+
#
|
150
|
+
# @return [String] The human-readable file size.
|
151
|
+
#######
|
152
|
+
def pix_humanize_bytes
|
153
|
+
bytes = self
|
154
|
+
if bytes < KB_BYTES
|
155
|
+
hsize = bytes
|
156
|
+
unit = bytes == A_BYTE ? HUMANIZED_BYTE_UNITS[A_BYTE] : HUMANIZED_BYTE_UNITS[B_BYTES]
|
157
|
+
|
158
|
+
elsif bytes < MB_BYTES
|
159
|
+
hsize = (bytes / KB_BYTES).round(2)
|
160
|
+
unit = HUMANIZED_BYTE_UNITS[KB_BYTES]
|
161
|
+
|
162
|
+
elsif bytes < GB_BYTES
|
163
|
+
hsize = (bytes / MB_BYTES).round(2)
|
164
|
+
unit = HUMANIZED_BYTE_UNITS[MB_BYTES]
|
165
|
+
|
166
|
+
elsif bytes < TB_BYTES
|
167
|
+
hsize = (bytes / GB_BYTES).round(2)
|
168
|
+
unit = HUMANIZED_BYTE_UNITS[GB_BYTES]
|
169
|
+
|
170
|
+
elsif bytes < PB_BYTES
|
171
|
+
hsize = (bytes / TB_BYTES).round(2)
|
172
|
+
unit = HUMANIZED_BYTE_UNITS[TB_BYTES]
|
173
|
+
|
174
|
+
else
|
175
|
+
hsize = (bytes / PB_BYTES).round(2)
|
176
|
+
unit = HUMANIZED_BYTE_UNITS[PB_BYTES]
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
"#{hsize} #{unit}"
|
181
|
+
end
|
182
|
+
|
183
|
+
end # module
|
184
|
+
|
185
|
+
end # module
|
186
|
+
|
187
|
+
end # module
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Copyright 2025 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
4
|
+
# at the root of this project.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
require 'pixar_ruby_extensions/integer/utils'
|
9
|
+
|
10
|
+
class Integer
|
11
|
+
|
12
|
+
include PixarRubyExtensions::IntegerExtensions::Utils
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Copyright 2025 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
4
|
+
# at the root of this project.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PixarRubyExtensions
|
9
|
+
|
10
|
+
module IPAddrExtensions
|
11
|
+
|
12
|
+
module Predicates
|
13
|
+
|
14
|
+
# Handy when you don't know if a value is a String or an IPAddr
|
15
|
+
#
|
16
|
+
# Does not start with pix_ so that you can call it on
|
17
|
+
# either a String or an IPAddr
|
18
|
+
#
|
19
|
+
# Because it doesn't start with pix_ we are only
|
20
|
+
# adding this if it doesn't already exist as an
|
21
|
+
# instance method
|
22
|
+
unless IPAddr.instance_methods.include? :start_with?
|
23
|
+
|
24
|
+
def start_with?(str)
|
25
|
+
to_s.start_with? str
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
# Handy when you don't know if a value is a String or an IPAddr
|
31
|
+
#
|
32
|
+
# Does not start with pix_ so that you can call it on
|
33
|
+
# either a String or an IPAddr
|
34
|
+
#
|
35
|
+
# Because it doesn't start with pix_ we are only
|
36
|
+
# adding this if it doesn't already exist as an
|
37
|
+
# instance method
|
38
|
+
unless IPAddr.instance_methods.include? :end_with?
|
39
|
+
|
40
|
+
def end_with?(str)
|
41
|
+
to_s.end_with? str
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end # module
|
47
|
+
|
48
|
+
end # module
|
49
|
+
|
50
|
+
end # module
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# Copyright 2025 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
4
|
+
# at the root of this project.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PixarRubyExtensions
|
9
|
+
|
10
|
+
module IPAddrExtensions
|
11
|
+
|
12
|
+
module Utils
|
13
|
+
|
14
|
+
# Convert starting and ending IPv4 IP addresses (either Strings or IPAddrs)
|
15
|
+
# into a single masked IPv4 IPAddr
|
16
|
+
#
|
17
|
+
# @param starting[Strings, IPAddr] the starting IP address
|
18
|
+
#
|
19
|
+
# @param ending[Strings, IPAddr] the ending IP address
|
20
|
+
#
|
21
|
+
# @return [IPAddr] the IP address range represented as a masked IPv4 address
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# IPAddr.j_masked_v4addr '10.0.0.0', '10.0.0.255' # => #<IPAddr: IPv4:10.0.0.0/255.255.255.0>
|
25
|
+
#
|
26
|
+
def pix_masked_v4addr(starting, ending)
|
27
|
+
IPAddr.new "#{starting}/#{j_cidr_from_ends(starting, ending)}"
|
28
|
+
end # self.j_masked_v4addr(starting,ending)
|
29
|
+
|
30
|
+
# Given starting and ending IPv4 IP addresses (either Strings or IPAddrs)
|
31
|
+
# return the CIDR notation routing prefix mask
|
32
|
+
#
|
33
|
+
# @param starting[Strings, IPAddr] the starting IP address
|
34
|
+
#
|
35
|
+
# @param ending[Strings, IPAddr] the ending IP address
|
36
|
+
#
|
37
|
+
# @return [FixNum] the CIDR notation routing prefix mask
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
# IPAddr.j_cidr_from_ends '10.0.0.0', '10.0.0.255' # => 24
|
41
|
+
#
|
42
|
+
def pix_cidr_from_ends(starting, ending)
|
43
|
+
starting = IPAddr.new(starting) unless starting.is_a? IPAddr
|
44
|
+
ending = IPAddr.new(ending) unless ending.is_a? IPAddr
|
45
|
+
|
46
|
+
# how many possible addresses in the range?
|
47
|
+
num_addrs = ending.to_i - starting.to_i + 1
|
48
|
+
|
49
|
+
# convert the number of possible addresses to
|
50
|
+
# binary then subtract the number of bits from
|
51
|
+
# the full length of an IPv4 addr
|
52
|
+
# (32 bits) and that gives the CIDR prefix
|
53
|
+
32 - num_addrs.to_s(2).length + 1
|
54
|
+
end # self.get_cidr(starting,ending)
|
55
|
+
|
56
|
+
# Convert a starting address (either String or IPAddr) and a
|
57
|
+
# CIDR notation routing prefix mask into the IPv4 address
|
58
|
+
# of at the end of the range of addresses.
|
59
|
+
#
|
60
|
+
# @param starting[Strings, IPAddr] the starting IP address
|
61
|
+
#
|
62
|
+
# @param cidr[FixNum] the CIDR mask
|
63
|
+
#
|
64
|
+
# @return [IPAddr] the ending IP address of the range.
|
65
|
+
#
|
66
|
+
# @example
|
67
|
+
# IPAddr.j_ending_address '10.0.0.0', 24 # => #<IPAddr: IPv4:10.0.0.255>
|
68
|
+
#
|
69
|
+
def pix_ending_address(starting, cidr)
|
70
|
+
IPAddr.new("#{starting}/#{cidr}").to_range.max
|
71
|
+
end # ending_address
|
72
|
+
|
73
|
+
end # module
|
74
|
+
|
75
|
+
end # module
|
76
|
+
|
77
|
+
end # module
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Copyright 2025 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
4
|
+
# at the root of this project.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
require 'ipaddr'
|
9
|
+
require 'pixar_ruby_extensions/ipaddr/utils'
|
10
|
+
require 'pixar_ruby_extensions/ipaddr/predicates'
|
11
|
+
|
12
|
+
############################################
|
13
|
+
# A few augmentations to IPAddr handling.
|
14
|
+
#
|
15
|
+
class IPAddr
|
16
|
+
|
17
|
+
extend PixarRubyExtensions::IPAddrExtensions::Utils
|
18
|
+
include PixarRubyExtensions::IPAddrExtensions::Predicates
|
19
|
+
|
20
|
+
end # Class IPAddr
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Copyright 2025 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
4
|
+
# at the root of this project.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PixarRubyExtensions
|
9
|
+
|
10
|
+
module JSONExtensions
|
11
|
+
|
12
|
+
# Add support for jsonlines (.jsonl) files
|
13
|
+
# See https://jsonlines.org/
|
14
|
+
#
|
15
|
+
# See also Array#pix_to_jsonl
|
16
|
+
#
|
17
|
+
module JSONL
|
18
|
+
|
19
|
+
# Read a jsonlines file and return an array of objects, with the addition of
|
20
|
+
# ignoring comment lines, as with JSONExtensions::Utils#pix_parse
|
21
|
+
#
|
22
|
+
# @param source [String] the string of JSON to be parsed
|
23
|
+
#
|
24
|
+
# @param comment_string [String] the string that marks the start
|
25
|
+
# of a comment line, possibly with leading whitespace. Default is '#'
|
26
|
+
#
|
27
|
+
# @return [Object] The parsed JSON
|
28
|
+
####################
|
29
|
+
def pix_parse_jsonl(source, comment_string: '#', **opts)
|
30
|
+
src = pix_strip_comments(source, comment_string: comment_string)
|
31
|
+
src.split("\n").map { |line| JSON.parse(line, **opts) }
|
32
|
+
end
|
33
|
+
|
34
|
+
# Generate a jsonlines string from an array of objects.
|
35
|
+
#
|
36
|
+
# @param objects [Array<Object>] the objects to be turned into jsonlines
|
37
|
+
#
|
38
|
+
# @return [String] The jsonlines string
|
39
|
+
####################
|
40
|
+
def pix_generate_jsonl(objects, **opts)
|
41
|
+
raise TypeError, "Expected an Array, got a #{objects.class}" unless objects.is_a? Array
|
42
|
+
|
43
|
+
objects.map { |obj| JSON.generate(obj, **opts) }.join("\n")
|
44
|
+
end
|
45
|
+
|
46
|
+
end # module
|
47
|
+
|
48
|
+
end # class
|
49
|
+
|
50
|
+
end # module
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Copyright 2025 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
4
|
+
# at the root of this project.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PixarRubyExtensions
|
9
|
+
|
10
|
+
module JSONExtensions
|
11
|
+
|
12
|
+
module Utils
|
13
|
+
|
14
|
+
# The same as JSON.parse, except whole-line comments are
|
15
|
+
# stripped from source before its parsed.
|
16
|
+
#
|
17
|
+
# Comment lines start with zero or more whitespace followed
|
18
|
+
# by the comment string, which by default is '#' but you
|
19
|
+
# can pass in others, such as '--'
|
20
|
+
#
|
21
|
+
# NOTE: Even though the JSON standard does not include
|
22
|
+
# support for comments, apprarently the Ruby JSON.parse
|
23
|
+
# method does honor '//' comments. I only discovered that
|
24
|
+
# when testing this method.
|
25
|
+
# I'm leaving it here though because we already use #
|
26
|
+
# comments, and that's the kind that YAML uses
|
27
|
+
#
|
28
|
+
# This command doesn't support or recognize in-line comments
|
29
|
+
# only whole-line comments.
|
30
|
+
#
|
31
|
+
# See JSON.parse for the standard opts and return value
|
32
|
+
#
|
33
|
+
# @param source [String] the string of JSON to be parsed
|
34
|
+
#
|
35
|
+
# @param comment_string [String] the string that marks the start
|
36
|
+
# of a comment line, possibly with leading whitespace.
|
37
|
+
#
|
38
|
+
# @return [Object] The parsed JSON
|
39
|
+
#
|
40
|
+
def pix_parse(source, comment_string: '#', **opts)
|
41
|
+
src = pix_strip_comments(source, comment_string: comment_string)
|
42
|
+
JSON.parse src, **opts
|
43
|
+
end
|
44
|
+
|
45
|
+
# See pix_parse and JSON.parse!
|
46
|
+
def pix_parse!(source, comment_string: '#', **opts)
|
47
|
+
src = pix_strip_comments(source, comment_string: comment_string)
|
48
|
+
JSON.parse! src, **opts
|
49
|
+
end
|
50
|
+
|
51
|
+
# See pix_parse and JSON.load_file
|
52
|
+
def pix_load_file(filespec, comment_string: '#', **opts)
|
53
|
+
pix_parse File.read(filespec), comment_string: comment_string, **opts
|
54
|
+
end
|
55
|
+
|
56
|
+
# See pix_parse and JSON.load_file!
|
57
|
+
def pix_load_file!(filespec, comment_string: '#', **opts)
|
58
|
+
pix_parse! File.read(filespec), comment_string: comment_string, **opts
|
59
|
+
end
|
60
|
+
|
61
|
+
# remove comment lines from a string
|
62
|
+
#
|
63
|
+
# @param source [String] the string from which to remove comment lines
|
64
|
+
#
|
65
|
+
# @param comment_string [String] the string that marks the
|
66
|
+
# start of a commend line, possibly with leading whitespce
|
67
|
+
#
|
68
|
+
# @return [String] the string with comment lines removed.
|
69
|
+
#
|
70
|
+
def pix_strip_comments(source, comment_string: '#')
|
71
|
+
source.lines.reject { |l| l =~ /^\s*#{comment_string}/ }.join
|
72
|
+
end
|
73
|
+
|
74
|
+
end # module
|
75
|
+
|
76
|
+
end # class
|
77
|
+
|
78
|
+
end # module
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Copyright 2025 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
4
|
+
# at the root of this project.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
require 'json'
|
9
|
+
require 'pixar_ruby_extensions/json/utils'
|
10
|
+
require 'pixar_ruby_extensions/json/jsonl'
|
11
|
+
|
12
|
+
module JSON
|
13
|
+
|
14
|
+
extend PixarRubyExtensions::JSONExtensions::Utils
|
15
|
+
extend PixarRubyExtensions::JSONExtensions::JSONL
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Copyright 2025 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
4
|
+
# at the root of this project.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PixarRubyExtensions
|
9
|
+
|
10
|
+
module ObjectExtensions
|
11
|
+
|
12
|
+
module Predicates
|
13
|
+
|
14
|
+
BOOLEANS = [true, false].freeze
|
15
|
+
|
16
|
+
# is an object an explict true or false?
|
17
|
+
#
|
18
|
+
# @return [Boolean]
|
19
|
+
#
|
20
|
+
def pix_boolean?
|
21
|
+
BOOLEANS.include? self
|
22
|
+
end
|
23
|
+
alias pix_bool? pix_boolean?
|
24
|
+
|
25
|
+
# Is an object nil, or empty?
|
26
|
+
#
|
27
|
+
# Handier, and broader, than constantly doing
|
28
|
+
# var.to_s.empty? and doesn't require coercion
|
29
|
+
#
|
30
|
+
# @return [Boolean]
|
31
|
+
#
|
32
|
+
def pix_empty?
|
33
|
+
if nil?
|
34
|
+
true
|
35
|
+
elsif respond_to?(:empty?)
|
36
|
+
empty?
|
37
|
+
else
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# pix_empty? was originally pix_blank?
|
43
|
+
alias pix_blank? pix_empty?
|
44
|
+
|
45
|
+
end # module
|
46
|
+
|
47
|
+
end # module
|
48
|
+
|
49
|
+
end # module
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Copyright 2025 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
4
|
+
# at the root of this project.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
require 'pixar_ruby_extensions/object/predicates'
|
9
|
+
|
10
|
+
# include the modules loaded above
|
11
|
+
class Object
|
12
|
+
|
13
|
+
include PixarRubyExtensions::ObjectExtensions::Predicates
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Copyright 2025 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
4
|
+
# at the root of this project.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PixarRubyExtensions
|
9
|
+
|
10
|
+
module PathnameExtensions
|
11
|
+
|
12
|
+
module Predicates
|
13
|
+
|
14
|
+
# Is this a real file rather than a symlink?
|
15
|
+
# @see FileTest.pix_real_file?
|
16
|
+
def pix_real_file?
|
17
|
+
FileTest.pix_real_file? self
|
18
|
+
end
|
19
|
+
|
20
|
+
# Is this a real directory rather than a symlink?
|
21
|
+
# @see FileTest.pix_real_directory?
|
22
|
+
def pix_real_directory?
|
23
|
+
FileTest.pix_real_directory? self
|
24
|
+
end
|
25
|
+
|
26
|
+
# does a path include another?
|
27
|
+
# i.e. is 'other' a descendant of self ?
|
28
|
+
def pix_include?(other)
|
29
|
+
eps = expand_path.to_s
|
30
|
+
oeps = other.expand_path.to_s
|
31
|
+
oeps != eps && oeps.start_with?(eps)
|
32
|
+
end
|
33
|
+
|
34
|
+
end # module
|
35
|
+
|
36
|
+
end # module
|
37
|
+
|
38
|
+
end # module
|