bblib 0.4.1 → 1.0.2
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
- data/.gitignore +12 -11
- data/.rspec +2 -2
- data/.travis.yml +4 -4
- data/CODE_OF_CONDUCT.md +13 -13
- data/Gemfile +4 -4
- data/LICENSE.txt +21 -21
- data/Rakefile +6 -6
- data/bblib.gemspec +34 -34
- data/bin/console +14 -14
- data/bin/setup +7 -7
- data/lib/array/bbarray.rb +2 -2
- data/lib/bblib.rb +1 -0
- data/lib/bblib/version.rb +1 -1
- data/lib/class/effortless.rb +2 -2
- data/lib/file/bbfile.rb +10 -8
- data/lib/hash/bbhash.rb +23 -15
- data/lib/hash/hash_struct.rb +1 -1
- data/lib/hash/tree_hash.rb +1 -1
- data/lib/hash_path/hash_path.rb +3 -3
- data/lib/hash_path/part.rb +2 -2
- data/lib/html/bbhtml.rb +1 -0
- data/lib/html/builder.rb +15 -6
- data/lib/html/tag.rb +74 -5
- data/lib/html/tag_set.rb +20 -0
- data/lib/logging/bblogging.rb +2 -1
- data/lib/mixins/attrs.rb +40 -25
- data/lib/mixins/bbmixins.rb +2 -0
- data/lib/mixins/family_tree.rb +12 -0
- data/lib/mixins/hooks.rb +8 -1
- data/lib/mixins/logger.rb +10 -10
- data/lib/mixins/prototype.rb +26 -0
- data/lib/mixins/simple_init.rb +47 -17
- data/lib/mixins/type_init.rb +21 -0
- data/lib/number/bbnumber.rb +90 -0
- data/lib/object/bbobject.rb +1 -5
- data/lib/opal/bbopal.rb +5 -0
- data/lib/os/bbos.rb +0 -63
- data/lib/string/bbstring.rb +22 -1
- data/lib/string/cases.rb +4 -4
- data/lib/time/bbtime.rb +27 -0
- data/lib/time/task_timer.rb +3 -1
- metadata +4 -2
- data/lib/os/bbsys.rb +0 -255
data/lib/string/cases.rb
CHANGED
@@ -2,7 +2,7 @@ module BBLib
|
|
2
2
|
def self.title_case(str, first_only: true)
|
3
3
|
str = str.to_s unless str.is_a?(String)
|
4
4
|
ignoreables = %w(a an the on upon and but or in with to)
|
5
|
-
regx =
|
5
|
+
regx = /\s+|\-|\_|(?<=\W|^)\"(?=\w|$)|(?<=\W|^)\'(?=\w|$)|\(|\)|\[|\]|\{|\}|\#/
|
6
6
|
spacing = str.scan(regx).to_a
|
7
7
|
words = str.split(regx).map do |word|
|
8
8
|
if ignoreables.include?(word.downcase)
|
@@ -40,16 +40,16 @@ module BBLib
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def self.delimited_case(str, delimiter = '_')
|
43
|
-
regx = /[[:space:]]+|[
|
43
|
+
regx = /[[:space:]]+|\s+|[^\w\d]+|\#{delimiter}+/
|
44
44
|
str.split(regx).join(delimiter)
|
45
45
|
end
|
46
46
|
|
47
47
|
def self.snake_case(str)
|
48
|
-
BBLib.delimited_case
|
48
|
+
BBLib.delimited_case(str, '_')
|
49
49
|
end
|
50
50
|
|
51
51
|
def self.method_case(str)
|
52
|
-
str.gsub(/(?<=[^^])([A-Z])/, '_\1').gsub(
|
52
|
+
str.gsub(/(?<=[^^])([A-Z])(?=[^A-Z\s])/, '_\1').gsub(/[\s\_]+/, '_').snake_case.downcase
|
53
53
|
end
|
54
54
|
|
55
55
|
def self.class_case(str)
|
data/lib/time/bbtime.rb
CHANGED
@@ -138,6 +138,31 @@ module BBLib
|
|
138
138
|
exp: %w(y yr yrs year years)
|
139
139
|
}
|
140
140
|
}.freeze
|
141
|
+
|
142
|
+
module Durations
|
143
|
+
TIME_TABLE = {
|
144
|
+
nanosecond: 0.000000001,
|
145
|
+
microsecond: 0.000001,
|
146
|
+
milisecond: 0.001,
|
147
|
+
second: 1,
|
148
|
+
minute: 60,
|
149
|
+
hour: 3_600,
|
150
|
+
day: 86_400,
|
151
|
+
week: 604_800_000,
|
152
|
+
month: 2_592_000,
|
153
|
+
year: 31_536_000
|
154
|
+
}.freeze
|
155
|
+
|
156
|
+
TIME_TABLE.each do |name, multiplier|
|
157
|
+
define_method(name) do
|
158
|
+
self * multiplier
|
159
|
+
end
|
160
|
+
|
161
|
+
define_method(name.pluralize) do
|
162
|
+
self * multiplier
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
141
166
|
end
|
142
167
|
|
143
168
|
class String
|
@@ -147,6 +172,8 @@ class String
|
|
147
172
|
end
|
148
173
|
|
149
174
|
class Numeric
|
175
|
+
include BBLib::Durations
|
176
|
+
|
150
177
|
def to_duration(input: :sec, stop: :milli, style: :medium)
|
151
178
|
BBLib.to_duration self, input: input, stop: stop, style: style
|
152
179
|
end
|
data/lib/time/task_timer.rb
CHANGED
@@ -7,8 +7,10 @@ module BBLib
|
|
7
7
|
# @attr [Integer] retention The number of runs to collect per task before truncation.
|
8
8
|
class TaskTimer
|
9
9
|
include Effortless
|
10
|
+
include Prototype unless BBLib.in_opal?
|
11
|
+
|
10
12
|
attr_hash :tasks, default: {}, serialize: false
|
11
|
-
attr_int_between
|
13
|
+
attr_int_between(-1, nil, :retention, default: 100)
|
12
14
|
|
13
15
|
# Returns an aggregated metric for a given type.
|
14
16
|
#
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bblib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Black
|
@@ -101,6 +101,7 @@ files:
|
|
101
101
|
- lib/html/bbhtml.rb
|
102
102
|
- lib/html/builder.rb
|
103
103
|
- lib/html/tag.rb
|
104
|
+
- lib/html/tag_set.rb
|
104
105
|
- lib/logging/bblogging.rb
|
105
106
|
- lib/mixins/attrs.rb
|
106
107
|
- lib/mixins/bbmixins.rb
|
@@ -108,13 +109,14 @@ files:
|
|
108
109
|
- lib/mixins/family_tree.rb
|
109
110
|
- lib/mixins/hooks.rb
|
110
111
|
- lib/mixins/logger.rb
|
112
|
+
- lib/mixins/prototype.rb
|
111
113
|
- lib/mixins/serializer.rb
|
112
114
|
- lib/mixins/simple_init.rb
|
115
|
+
- lib/mixins/type_init.rb
|
113
116
|
- lib/number/bbnumber.rb
|
114
117
|
- lib/object/bbobject.rb
|
115
118
|
- lib/opal/bbopal.rb
|
116
119
|
- lib/os/bbos.rb
|
117
|
-
- lib/os/bbsys.rb
|
118
120
|
- lib/string/bbstring.rb
|
119
121
|
- lib/string/cases.rb
|
120
122
|
- lib/string/fuzzy_matcher.rb
|
data/lib/os/bbsys.rb
DELETED
@@ -1,255 +0,0 @@
|
|
1
|
-
|
2
|
-
module BBLib
|
3
|
-
module OS
|
4
|
-
def self.cpu_usages
|
5
|
-
if windows?
|
6
|
-
{ total: `wmic cpu get loadpercentage /format:value`.extract_numbers.first.to_f }
|
7
|
-
elsif linux? || mac?
|
8
|
-
system_stats[:cpu]
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.up_since
|
13
|
-
Time.now - uptime
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.uptime
|
17
|
-
if windows?
|
18
|
-
uptime = `net statistics server`.split("\n").find { |l| l.start_with?('Statistics since ') }.split(/since /i).last.strip
|
19
|
-
Time.now - Time.strptime(uptime, '%m/%d/%Y %l:%M:%S %p')
|
20
|
-
else
|
21
|
-
`cat /proc/uptime`.extract_numbers.first
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.cpu_used_p
|
26
|
-
cpu_usages[:total]
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.cpu_free_p
|
30
|
-
100 - cpu_used
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.current_memory_usage(output = :byte)
|
34
|
-
if windows?
|
35
|
-
`tasklist /FI "PID eq #{$$}" /FO list`
|
36
|
-
.split("\n").find { |l| l =~ /^Mem Usage:/ }&.gsub(',', '').parse_file_size(output: output)
|
37
|
-
else
|
38
|
-
processes.find { |pr| pr[:pid] == $$ }[:memory]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.mem_total
|
43
|
-
if windows?
|
44
|
-
`wmic computersystem get TotalPhysicalMemory`.extract_numbers.first / 1024.0
|
45
|
-
elsif linux?
|
46
|
-
system_stats.hpath('memory.total')
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.mem_used
|
51
|
-
mem_total.to_f - mem_free.to_f
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.mem_used_p
|
55
|
-
(mem_used.to_f / mem_total.to_f) * 100.0
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.mem_free
|
59
|
-
if windows?
|
60
|
-
`wmic os get freephysicalmemory /format:value`.extract_numbers.first
|
61
|
-
elsif linux?
|
62
|
-
system_stats.hpath('memory.free')
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.mem_free_p
|
67
|
-
(mem_free.to_f / mem_total.to_f) * 100.0
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.system_stats
|
71
|
-
if windows?
|
72
|
-
memfree = mem_free
|
73
|
-
memtotal = mem_total
|
74
|
-
memused = memtotal - memfree
|
75
|
-
{
|
76
|
-
cpu: cpu_usages,
|
77
|
-
memory: {
|
78
|
-
free: memfree,
|
79
|
-
used: memused,
|
80
|
-
total: memtotal,
|
81
|
-
free_p: (memfree / memtotal.to_f) * 100,
|
82
|
-
used_p: (memused / memtotal.to_f) * 100
|
83
|
-
},
|
84
|
-
uptime: uptime
|
85
|
-
}
|
86
|
-
else
|
87
|
-
stats = `top -b -n2 -d 0.1`.split("\n")
|
88
|
-
cpu = stats.find_all { |l| l =~ /\A\%?Cpu\(s\)/i }.last.extract_numbers
|
89
|
-
loads = stats.find_all { |l| l =~ / load average\: /i }.last.scan(/load average:.*/i).first.extract_numbers
|
90
|
-
mem = stats.find_all { |l| l =~ /KiB Mem|Mem\:/i }.last.extract_numbers
|
91
|
-
time = `cat /proc/uptime`.extract_numbers
|
92
|
-
{
|
93
|
-
cpu: {
|
94
|
-
user: cpu[0],
|
95
|
-
system: cpu[1],
|
96
|
-
nice: cpu[2],
|
97
|
-
total: cpu[0..2].inject(0) { |sum, v| sum += v.to_f },
|
98
|
-
idle: cpu[3],
|
99
|
-
wait: cpu[4],
|
100
|
-
hardware_interrupts: cpu[5],
|
101
|
-
software_interrupts: cpu[6],
|
102
|
-
hypervisor: cpu[7]
|
103
|
-
},
|
104
|
-
uptime: time[0],
|
105
|
-
uptime_idle: time[1],
|
106
|
-
memory: {
|
107
|
-
free: mem[1],
|
108
|
-
used: mem[2],
|
109
|
-
total: mem[0],
|
110
|
-
cache: mem[3],
|
111
|
-
free_p: (mem[1] / mem[0].to_f) * 100,
|
112
|
-
used_p: (mem[2] / mem[0].to_f) * 100
|
113
|
-
},
|
114
|
-
load_average: {
|
115
|
-
1 => loads[0],
|
116
|
-
5 => loads[1],
|
117
|
-
15 => loads[2]
|
118
|
-
}
|
119
|
-
}
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.processes
|
124
|
-
if windows?
|
125
|
-
tasks = `tasklist /v`
|
126
|
-
cpu = `wmic path win32_perfformatteddata_perfproc_process get PercentProcessorTime,percentusertime,IDProcess /format:list`
|
127
|
-
cpu = cpu.split("\n\n\n\n").reject(&:empty?)
|
128
|
-
.map { |l| l.scan(/\d+/).map(&:to_i) }
|
129
|
-
.map { |n| [n[0], { cpu: n[1], user: n[2] }] }.to_h
|
130
|
-
lines = tasks.split("\n")[3..-1].map { |l| l.split(/\s{2,}/) }
|
131
|
-
cmds = `wmic process get processid,commandline /format:csv`.split("\n")[1..-1].reject { |r| r.strip == '' }
|
132
|
-
.map { |l| l.split(',')[1..-1] }
|
133
|
-
.map { |l| [l.last.to_i, l[0..-2].join(',')] }.to_h
|
134
|
-
lines.map do |l|
|
135
|
-
pid = l[1].extract_numbers.first
|
136
|
-
{
|
137
|
-
name: l[0],
|
138
|
-
pid: pid,
|
139
|
-
user: l[4],
|
140
|
-
cpu: (cpu[pid][:cpu] rescue nil),
|
141
|
-
memory: (((l[3].delete(',').extract_numbers.first / mem_total) * 100) rescue nil),
|
142
|
-
cmd: cmds[pid]
|
143
|
-
}
|
144
|
-
end
|
145
|
-
else
|
146
|
-
t = `ps -e -o comm,pid,ruser,%cpu,%mem,cmd`
|
147
|
-
lines = t.split("\n")[1..-1].map { |l| l.split(/\s+/) }
|
148
|
-
lines.map { |l| l.size == 6 ? l : [l[0], l[1], l[2], l[3], l[4], l[5..-1].join(' ')] }
|
149
|
-
lines.map do |l|
|
150
|
-
{
|
151
|
-
name: l[0],
|
152
|
-
pid: l[1].to_i,
|
153
|
-
user: l[2],
|
154
|
-
cpu: l[3].to_f,
|
155
|
-
memory: l[4].to_f,
|
156
|
-
cmd: l[5]
|
157
|
-
}
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def self.process_list
|
163
|
-
if windows?
|
164
|
-
tasks = `tasklist /v`
|
165
|
-
lines = tasks.split("\n")[3..-1].map { |l| l.split(/\s{2,}/) }
|
166
|
-
else
|
167
|
-
t = `ps -e -o comm,pid,ruser,%cpu,%mem,cmd`
|
168
|
-
lines = t.split("\n")[1..-1].map { |l| l.split(/\s+/) }
|
169
|
-
lines.map { |l| l.size == 6 ? l : [l[0], l[1], l[2], l[3], l[4], l[5..-1].join(' ')] }
|
170
|
-
end
|
171
|
-
lines.map { |l| l[0] }.sort
|
172
|
-
end
|
173
|
-
|
174
|
-
def self.filesystems
|
175
|
-
if windows?
|
176
|
-
types = {
|
177
|
-
0 => 'Unknown',
|
178
|
-
1 => 'No Root Directory',
|
179
|
-
2 => 'Removable Disk',
|
180
|
-
3 => 'Local Disk',
|
181
|
-
4 => 'Network Drive',
|
182
|
-
5 => 'Compact Disc',
|
183
|
-
6 => 'RAM Disk'
|
184
|
-
}
|
185
|
-
parse_wmic('wmic logicaldisk get name,description,filesystem,freespace,size,volumename,volumeserialnumber,providername,drivetype')
|
186
|
-
.map do |v|
|
187
|
-
v.hpath_move(
|
188
|
-
'freespace' => 'free',
|
189
|
-
'providername' => 'provider',
|
190
|
-
'volumename' => 'volume_name',
|
191
|
-
'volumeserialnumber' => 'serial_number',
|
192
|
-
'filesystem' => 'filesystem_type',
|
193
|
-
'name' => 'disk'
|
194
|
-
)
|
195
|
-
dt = v.delete(:drivetype).to_i
|
196
|
-
v[:type] = types[dt]
|
197
|
-
if (2..4) === dt
|
198
|
-
v[:free] = v[:free].to_i
|
199
|
-
v[:size] = v[:size].to_i
|
200
|
-
v[:used] = v[:size] - v[:free]
|
201
|
-
v[:free_p] = (v[:free] / v[:size].to_f) * 100
|
202
|
-
v[:free_p] = nil if v[:free_p].nan?
|
203
|
-
v[:used_p] = (v[:used] / v[:size].to_f) * 100
|
204
|
-
v[:used_p] = nil if v[:used_p].nan?
|
205
|
-
end
|
206
|
-
v
|
207
|
-
end
|
208
|
-
else
|
209
|
-
`df -aTB 1`
|
210
|
-
.split("\n")[1..-1]
|
211
|
-
.map { |l| l.split(/\s{2,}|(?<=\d)\s|(?<=%)\s|(?<=\-)\s|(?<=\w)\s+(?=\w+\s+\d)/) }
|
212
|
-
.map do |i|
|
213
|
-
{
|
214
|
-
filesystem: i[0],
|
215
|
-
type: i[1],
|
216
|
-
size: i[2].to_i,
|
217
|
-
used: i[3].to_i,
|
218
|
-
available: i[4].to_i,
|
219
|
-
used_p: i[5].extract_integers.first.to_f,
|
220
|
-
mount: i[6]
|
221
|
-
}
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
# A mostly platform agnostic call to get root volumes
|
227
|
-
def self.root_volumes
|
228
|
-
if BBLib.windows?
|
229
|
-
begin # For windows
|
230
|
-
`wmic logicaldisk get name`.split("\n").map(&:strip)[1..-1].reject { |r| r == '' }
|
231
|
-
rescue
|
232
|
-
begin # Windows attempt 2
|
233
|
-
`fsutil fsinfo drives`.scan(/(?<=\s)\w\:/)
|
234
|
-
rescue
|
235
|
-
nil
|
236
|
-
end
|
237
|
-
end
|
238
|
-
else
|
239
|
-
begin
|
240
|
-
`ls /`.split("\n").map(&:strip).reject { |r| r == '' }
|
241
|
-
rescue # All attempts failed
|
242
|
-
nil
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
# Windows only method to get the volume labels of disk drives
|
248
|
-
def self.root_volume_labels
|
249
|
-
return nil unless BBLib.windows?
|
250
|
-
`wmic logicaldisk get caption,volumename`.split("\n")[1..-1]
|
251
|
-
.map { |m| [m.split(' ').first.to_s.strip, m.split(' ')[1..-1].to_a.join(' ').strip] }
|
252
|
-
.reject { |o, _t| o == '' }.to_h
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|