sapis 0.1.0 → 0.2.0
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/lib/sapis/bash_helper.rb +17 -20
- data/lib/sapis/computations_helper.rb +15 -18
- data/lib/sapis/concurrency_helper.rb +17 -21
- data/lib/sapis/configuration_helper.rb +30 -32
- data/lib/sapis/desktop_helper.rb +6 -8
- data/lib/sapis/generic_helper.rb +7 -7
- data/lib/sapis/gnome_helper.rb +1 -4
- data/lib/sapis/graphing_helper.rb +48 -51
- data/lib/sapis/interactions_helper.rb +27 -30
- data/lib/sapis/multimedia_helper.rb +71 -74
- data/lib/sapis/sqlite_layer.rb +38 -39
- data/lib/sapis/system_helper.rb +27 -30
- data/lib/sapis/version.rb +1 -1
- metadata +19 -5
data/lib/sapis/sqlite_layer.rb
CHANGED
|
@@ -27,12 +27,12 @@ class Rollback < StandardError; end
|
|
|
27
27
|
class SQLiteLayer
|
|
28
28
|
attr_reader :db
|
|
29
29
|
|
|
30
|
-
def initialize(
|
|
31
|
-
absolute_db_filename = options[
|
|
30
|
+
def initialize(filename, options={})
|
|
31
|
+
absolute_db_filename = options[:relative] ? File.expand_path(filename, '~') : filename
|
|
32
32
|
|
|
33
|
-
@db = SQLite3::Database.new(
|
|
33
|
+
@db = SQLite3::Database.new(absolute_db_filename)
|
|
34
34
|
|
|
35
|
-
@db.execute(
|
|
35
|
+
@db.execute('PRAGMA foreign_keys = ON')
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
# values: Can be either an array of values, or a hash field=>value.
|
|
@@ -45,8 +45,8 @@ class SQLiteLayer
|
|
|
45
45
|
# values are not automatically escaped or quoted.
|
|
46
46
|
# this makes sense for some edge cases.
|
|
47
47
|
#
|
|
48
|
-
def insert_values(
|
|
49
|
-
straight_insert = options[
|
|
48
|
+
def insert_values(table, values, options={})
|
|
49
|
+
straight_insert = options[:straight_insert] || {}
|
|
50
50
|
|
|
51
51
|
sql_fields = []
|
|
52
52
|
sql_placeholders = []
|
|
@@ -54,97 +54,97 @@ class SQLiteLayer
|
|
|
54
54
|
|
|
55
55
|
case values
|
|
56
56
|
when Hash
|
|
57
|
-
values.each do |
|
|
57
|
+
values.each do |field, value|
|
|
58
58
|
sql_fields << field.to_s
|
|
59
59
|
sql_placeholders << '?'
|
|
60
60
|
sql_values << value
|
|
61
61
|
end
|
|
62
62
|
when Array
|
|
63
|
-
values.each do |
|
|
63
|
+
values.each do |value|
|
|
64
64
|
sql_placeholders << '?'
|
|
65
65
|
sql_values << value
|
|
66
66
|
end
|
|
67
67
|
else
|
|
68
|
-
raise "Invalid values class: #{
|
|
68
|
+
raise "Invalid values class: #{values.class}"
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
straight_insert.each do |
|
|
71
|
+
straight_insert.each do |field, value|
|
|
72
72
|
sql_fields << field.to_s
|
|
73
73
|
sql_placeholders << value
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
sql_values.each_with_index do |
|
|
77
|
-
sql_values[
|
|
76
|
+
sql_values.each_with_index do |value, i|
|
|
77
|
+
sql_values[i] = SQLite3::Blob.new(value.first) if value.is_a?(Array)
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
sql = "INSERT INTO #{
|
|
81
|
-
sql << "( #{
|
|
82
|
-
sql << " VALUES( #{
|
|
80
|
+
sql = "INSERT INTO #{table}"
|
|
81
|
+
sql << "( #{sql_fields.join(', ')} )" if sql_fields.size > 0
|
|
82
|
+
sql << " VALUES( #{sql_placeholders.join(', ')} )"
|
|
83
83
|
|
|
84
|
-
@db.execute(
|
|
84
|
+
@db.execute(sql, sql_values)
|
|
85
85
|
|
|
86
86
|
@db.last_insert_row_id
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
# values: the :where key is the where condition
|
|
90
90
|
#
|
|
91
|
-
def update_values(
|
|
92
|
-
where_sql = values.delete(
|
|
91
|
+
def update_values(table, values)
|
|
92
|
+
where_sql = values.delete(:where) || 'TRUE'
|
|
93
93
|
|
|
94
|
-
set_sql, set_values = values.inject(
|
|
94
|
+
set_sql, set_values = values.inject(["", []]) do |(current_set_sql, current_set_values), (column, value)|
|
|
95
95
|
current_set_sql << ', ' if current_set_sql != ''
|
|
96
|
-
current_set_sql << "#{
|
|
96
|
+
current_set_sql << "#{column} = ?"
|
|
97
97
|
current_set_values << value
|
|
98
|
-
[
|
|
98
|
+
[current_set_sql, current_set_values]
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
-
@db.execute(
|
|
101
|
+
@db.execute("UPDATE #{table} SET #{set_sql} WHERE #{where_sql}", set_values)
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
-
def execute(
|
|
105
|
-
@db.execute(
|
|
104
|
+
def execute(sql, *params)
|
|
105
|
+
@db.execute(sql, params)
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
-
def select(
|
|
109
|
-
options = params.last.is_a?(
|
|
110
|
-
execute(
|
|
108
|
+
def select(sql, *params)
|
|
109
|
+
options = params.last.is_a?(Hash) ? params.pop : {}
|
|
110
|
+
execute(sql, *params)
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
# params: the last can be :options
|
|
114
114
|
# options:
|
|
115
115
|
# :force: force finding a value
|
|
116
116
|
#
|
|
117
|
-
def select_value(
|
|
118
|
-
options = params.last.is_a?(
|
|
117
|
+
def select_value(sql, *params)
|
|
118
|
+
options = params.last.is_a?(Hash) ? params.pop : {}
|
|
119
119
|
|
|
120
|
-
row = execute(
|
|
120
|
+
row = execute(sql, *params).first
|
|
121
121
|
|
|
122
122
|
value = row && row.first
|
|
123
123
|
|
|
124
124
|
if value
|
|
125
125
|
value
|
|
126
|
-
elsif options[
|
|
126
|
+
elsif options[:force]
|
|
127
127
|
raise "Value not found!"
|
|
128
128
|
end
|
|
129
129
|
end
|
|
130
130
|
|
|
131
|
-
def select_all(
|
|
132
|
-
column_names, *raw_data = select_with_headers(
|
|
131
|
+
def select_all(sql, *params)
|
|
132
|
+
column_names, *raw_data = select_with_headers(sql, *params)
|
|
133
133
|
|
|
134
|
-
raw_data.map do |
|
|
135
|
-
Hash[
|
|
134
|
+
raw_data.map do |row|
|
|
135
|
+
Hash[column_names.zip(row)]
|
|
136
136
|
end
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
# This is a :select_row with headers as first row.
|
|
140
140
|
#
|
|
141
|
-
def select_with_headers(
|
|
142
|
-
@db.execute2(
|
|
141
|
+
def select_with_headers(sql, *params)
|
|
142
|
+
@db.execute2(sql, params)
|
|
143
143
|
end
|
|
144
144
|
|
|
145
145
|
# Can be nested - only the outer call with start a transaction.
|
|
146
146
|
#
|
|
147
|
-
def transaction(
|
|
147
|
+
def transaction(commit=true, &block)
|
|
148
148
|
if @db.transaction_active?
|
|
149
149
|
yield
|
|
150
150
|
else
|
|
@@ -162,5 +162,4 @@ class SQLiteLayer
|
|
|
162
162
|
def close
|
|
163
163
|
@db.close
|
|
164
164
|
end
|
|
165
|
-
|
|
166
165
|
end
|
data/lib/sapis/system_helper.rb
CHANGED
|
@@ -18,10 +18,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
18
18
|
|
|
19
19
|
=end
|
|
20
20
|
|
|
21
|
-
require File.expand_path(
|
|
21
|
+
require File.expand_path('../bash_helper.rb', __FILE__)
|
|
22
22
|
|
|
23
23
|
module SystemHelper
|
|
24
|
-
|
|
25
24
|
require 'shellwords'
|
|
26
25
|
|
|
27
26
|
SystemHelper::SEARCH_FILES = 'f'
|
|
@@ -35,13 +34,13 @@ module SystemHelper
|
|
|
35
34
|
|
|
36
35
|
def self.current_timezone
|
|
37
36
|
if mac?
|
|
38
|
-
`systemsetup -gettimezone`.strip.sub(
|
|
37
|
+
`systemsetup -gettimezone`.strip.sub('Time Zone: ', '')
|
|
39
38
|
else
|
|
40
|
-
IO.read(
|
|
39
|
+
IO.read('/etc/timezone').chomp
|
|
41
40
|
end
|
|
42
41
|
end
|
|
43
42
|
|
|
44
|
-
def self.symlink(
|
|
43
|
+
def self.symlink(source, destination)
|
|
45
44
|
# Doesn't work! At least one bug in the library:
|
|
46
45
|
# - File.exists? returns false if a symlink exists, but points to a non-existent file
|
|
47
46
|
# - symlink causes an abrupt exit if the destination exists
|
|
@@ -56,54 +55,54 @@ module SystemHelper
|
|
|
56
55
|
# 'mountpoint' has inconsistent exit behavior, because if the path is not a mountpoint,
|
|
57
56
|
# it returns 1, but prints the message to stdout.
|
|
58
57
|
#
|
|
59
|
-
def unmount_base_mountpoint(
|
|
58
|
+
def unmount_base_mountpoint(filename)
|
|
60
59
|
while filename != '/'
|
|
61
|
-
is_mountpoint = `mountpoint #{
|
|
60
|
+
is_mountpoint = `mountpoint #{encode_bash_filenames(filename)}` =~ /is a mountpoint\n$/
|
|
62
61
|
|
|
63
62
|
if is_mountpoint
|
|
64
63
|
simple_bash_execute "umount", filename
|
|
65
64
|
return
|
|
66
65
|
end
|
|
67
66
|
|
|
68
|
-
filename = File.dirname(
|
|
67
|
+
filename = File.dirname(filename)
|
|
69
68
|
end
|
|
70
69
|
|
|
71
|
-
raise "Couldn't find base mount point for file: #{
|
|
70
|
+
raise "Couldn't find base mount point for file: #{filename}"
|
|
72
71
|
end
|
|
73
72
|
|
|
74
73
|
def system_cores_number
|
|
75
74
|
if RUBY_PLATFORM =~ /darwin/i
|
|
76
75
|
raw_result = safe_execute "system_profiler SPHardwareDataType | grep 'Total Number Of Cores'"
|
|
77
|
-
raw_result[
|
|
76
|
+
raw_result[/: (\d+)/, 1].to_i
|
|
78
77
|
else
|
|
79
78
|
# See https://www.ibm.com/developerworks/community/blogs/brian/entry/linux_show_the_number_of_cpu_cores_on_your_system17?lang=en
|
|
80
79
|
# Bash form:
|
|
81
80
|
#
|
|
82
81
|
# cat /proc/cpuinfo | egrep "core id|physical id" | tr -d "\n" | sed s/physical/\\nphysical/g | grep -v ^$ | sort | uniq | wc -l
|
|
83
82
|
#
|
|
84
|
-
IO.readlines(
|
|
83
|
+
IO.readlines('/proc/cpuinfo').grep(/core id|physical id/).each_slice(2).to_a.uniq.size
|
|
85
84
|
end
|
|
86
85
|
end
|
|
87
86
|
|
|
88
|
-
def unrar(
|
|
89
|
-
delete = !!
|
|
87
|
+
def unrar(file, options={})
|
|
88
|
+
delete = !!options[:delete]
|
|
90
89
|
|
|
91
90
|
original_dir = Dir.pwd
|
|
92
|
-
destination_dir = File.dirname(
|
|
91
|
+
destination_dir = File.dirname(file)
|
|
93
92
|
|
|
94
|
-
Dir.chdir(
|
|
93
|
+
Dir.chdir(destination_dir)
|
|
95
94
|
|
|
96
95
|
simple_bash_execute "unrar x", file
|
|
97
96
|
|
|
98
|
-
File.delete(
|
|
97
|
+
File.delete(file) if delete
|
|
99
98
|
ensure
|
|
100
|
-
Dir.chdir(
|
|
99
|
+
Dir.chdir(original_dir)
|
|
101
100
|
end
|
|
102
101
|
|
|
103
102
|
# Opens :filename using the default executable.
|
|
104
103
|
#
|
|
105
|
-
def self.open_file(
|
|
106
|
-
`xdg-open #{
|
|
104
|
+
def self.open_file(filename)
|
|
105
|
+
`xdg-open #{filename.shellescape}`
|
|
107
106
|
end
|
|
108
107
|
|
|
109
108
|
# Case insensitive search
|
|
@@ -112,11 +111,11 @@ module SystemHelper
|
|
|
112
111
|
# :file_type: [nil] either SEARCH_FILES or SEARCH_DIRECTORIES, or nil for both.
|
|
113
112
|
# :skip_paths: [nil] array of (full) paths to skip
|
|
114
113
|
#
|
|
115
|
-
def self.find_files(
|
|
116
|
-
search_paths = raw_search_paths.map { |
|
|
114
|
+
def self.find_files(raw_pattern, raw_search_paths, options={})
|
|
115
|
+
search_paths = raw_search_paths.map { |path| path.shellescape }.join(' ')
|
|
117
116
|
pattern = raw_pattern.shellescape
|
|
118
117
|
|
|
119
|
-
case options[
|
|
118
|
+
case options[:file_type]
|
|
120
119
|
when SEARCH_FILES
|
|
121
120
|
file_type = '-type f'
|
|
122
121
|
when SEARCH_DIRECTORIES
|
|
@@ -124,18 +123,16 @@ module SystemHelper
|
|
|
124
123
|
when nil
|
|
125
124
|
# nothing
|
|
126
125
|
else
|
|
127
|
-
raise "Unrecognized :file_type option for find_files: #{
|
|
126
|
+
raise "Unrecognized :file_type option for find_files: #{options[:file_type]}"
|
|
128
127
|
end
|
|
129
128
|
|
|
130
|
-
skip_paths = options[
|
|
131
|
-
path_with_pattern = File.join(
|
|
129
|
+
skip_paths = options[:skip_paths].to_a.map do |path|
|
|
130
|
+
path_with_pattern = File.join(path, '*')
|
|
132
131
|
" -not -path " + path_with_pattern.shellescape
|
|
133
|
-
end.join(
|
|
132
|
+
end.join(' ')
|
|
134
133
|
|
|
135
|
-
raw_result = `find #{
|
|
134
|
+
raw_result = `find #{search_paths} -iname #{pattern} #{file_type} #{skip_paths}`.chomp
|
|
136
135
|
|
|
137
|
-
raw_result.split(
|
|
136
|
+
raw_result.split("\n")
|
|
138
137
|
end
|
|
139
|
-
|
|
140
138
|
end
|
|
141
|
-
|
data/lib/sapis/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sapis
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Saverio Miroddi
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 2026-01-19 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: gruff
|
|
@@ -57,14 +57,14 @@ dependencies:
|
|
|
57
57
|
requirements:
|
|
58
58
|
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version:
|
|
60
|
+
version: 2.9.0
|
|
61
61
|
type: :runtime
|
|
62
62
|
prerelease: false
|
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
65
|
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version:
|
|
67
|
+
version: 2.9.0
|
|
68
68
|
- !ruby/object:Gem::Dependency
|
|
69
69
|
name: rake
|
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -93,6 +93,20 @@ dependencies:
|
|
|
93
93
|
- - "~>"
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
95
|
version: '3.0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: rubocop
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: 1.82.1
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: 1.82.1
|
|
96
110
|
description: A collection of utility helpers for Ruby including graphing, configuration
|
|
97
111
|
management, concurrency, system operations, multimedia handling, and more.
|
|
98
112
|
email: []
|
|
@@ -135,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
135
149
|
- !ruby/object:Gem::Version
|
|
136
150
|
version: '0'
|
|
137
151
|
requirements: []
|
|
138
|
-
rubygems_version: 3.6.
|
|
152
|
+
rubygems_version: 3.6.9
|
|
139
153
|
specification_version: 4
|
|
140
154
|
summary: Sav's APIs - A collection of Ruby utility helpers
|
|
141
155
|
test_files: []
|