console_utils 0.6.2 → 0.10.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0b8ff5ade51bb1eeb010dd6c9bb40afcbd54ac9d
4
- data.tar.gz: d94d2684a740245b6d3e541c812ab03785cdc23c
2
+ SHA256:
3
+ metadata.gz: 9fd306eed79667af72048f0d5e5ed12c1bd6c0859c260e8d6523af47f81c88b2
4
+ data.tar.gz: d0bd5a629c0711fbb44e2a71e113dc41e0fda5faa8d56af937b97c0eeb480c73
5
5
  SHA512:
6
- metadata.gz: 59bee05607a89edf2b91ec1730f2b25ca544f61cb9cccc3253eadd93ffe76e01fba31012a13076fbea7ed721934ecff9cd31bb9c6a02474fe92346faf3ece8cf
7
- data.tar.gz: 33b2f85d32e419a10707081436867634d5c87edb8f177a3c9206cfe15c5ecea447049f6da5ad05801033e4ee18e4758e7f4af246ffd8fbc62dcde4017f9695bb
6
+ metadata.gz: 8abf3c1a57509b08e0cc61759ba3e5dc2c31b6cd88b90a751e86748e0b08a1ae8e6afa9cd46b1530c121b14ed9c40b62eebcf982090bebbdb19d4eca119b4184
7
+ data.tar.gz: f0000009774f5a91aa9ee63b5fff8127780f332d58c9b0aba6586056d56ad4bb0a3a9bb8e5a32f288c7fa1a67db9777a24d02cad9ea8349a5cecdf981fbac541
data/README.md CHANGED
@@ -184,7 +184,7 @@ Also provides shorthand to find any user by id: `usr(id)`
184
184
  ## OtherUtils
185
185
 
186
186
  #### clr()
187
- Term::ANSIColor shorthand
187
+ [Pastel](https://github.com/piotrmurach/pastel) shorthand
188
188
 
189
189
  #### shutting(:engine_key[, to: logger_level]) {}
190
190
  Shuts up the logger of a specified Rails engine for a given key (`:rails`, `:record`, `:controller` or `:view`).
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ["lib"]
21
21
  spec.required_ruby_version = ">= 2.1"
22
22
 
23
- spec.add_dependency "activesupport", ">= 4.1", "< 6"
24
- spec.add_dependency "term-ansicolor"
23
+ spec.add_dependency "activesupport", ">= 5.2", "< 7"
24
+ spec.add_dependency "pastel"
25
25
  spec.add_dependency "awesome_print"
26
26
  spec.add_dependency "benchmark-ips"
27
27
  spec.add_dependency "pry-rails"
@@ -1,7 +1,7 @@
1
1
  require 'active_support'
2
2
  require 'active_support/core_ext'
3
3
  require 'active_support/tagged_logging'
4
- require 'term/ansicolor'
4
+ require 'pastel'
5
5
  require 'console_utils/core_ext/array_to_proc'
6
6
  require 'console_utils/core_ext/local_values'
7
7
  require 'console_utils/version'
@@ -140,6 +140,12 @@ module ConsoleUtils
140
140
  # which is useful when using the +simple_token_automator+ gem.
141
141
  mattr_accessor(:auth_automator) { ConsoleUtils::RequestUtils::DefaultAuthAutomator }
142
142
 
143
+ # :attr:
144
+ # Keeps any amount of callable objects to invoke them before each request,
145
+ # with an instance of <tt>ConsoleUtils::RequestUtils::RequestParams</tt>
146
+ # as only the argument.
147
+ # (default: <tt>[]</tt>)
148
+ mattr_accessor(:request_hooks) { [] }
143
149
 
144
150
  # :section: Class Methods
145
151
 
@@ -201,6 +207,10 @@ module ConsoleUtils
201
207
  def setup_modules_to(context = nil)
202
208
  ReplState.setup(context)
203
209
  end
210
+
211
+ def pastel
212
+ @pastel ||= Pastel.new
213
+ end
204
214
  end
205
215
 
206
216
  ActiveSupport.run_load_hooks(:console_utils, self)
@@ -6,7 +6,7 @@ module ConsoleUtils #:nodoc:
6
6
 
7
7
  def self.extended(mod)
8
8
  ActiveSupport.on_load(:active_record) do
9
- ActiveRecord::Relation.send(:include, RandomRecord::FinderMethods)
9
+ ActiveRecord::Relation.send(:prepend, RandomRecord::FinderMethods)
10
10
  ActiveRecord::Base.send(:extend, RandomRecord::Querying)
11
11
  end
12
12
  end
@@ -9,8 +9,16 @@ module ConsoleUtils::ActiveRecordUtils #:nodoc:
9
9
  random.first
10
10
  end
11
11
 
12
- def anyid
13
- model.type_for_attribute('id').send(:cast_value, connection.select_value(select(:id).random.limit(1)))
12
+ def anyid(n = nil)
13
+ if n
14
+ @_anyid_history[-n.abs].presence || anyid()
15
+ else
16
+ idval = connection.select_value(select(:id).random.limit(1))
17
+ model.type_for_attribute('id').send(:cast_value, idval).tap do |result|
18
+ (@_anyid_history ||= []) << result
19
+ @_anyid_history.shift if @_anyid_history.size > 10
20
+ end
21
+ end
14
22
  end
15
23
  end
16
24
 
@@ -1,8 +1,8 @@
1
1
  module ConsoleUtils #:nodoc:
2
2
  module OtherUtils
3
- # <tt>Term::ANSIColor</tt> shorthand
3
+ # <tt>Pastel</tt> shorthand
4
4
  def clr
5
- Term::ANSIColor
5
+ ConsoleUtils.pastel
6
6
  end
7
7
 
8
8
  # :call-seq:
@@ -1,7 +1,6 @@
1
1
  module ConsoleUtils::RequestUtils
2
2
  class DefaultAuthAutomator
3
3
  def self.call(rq)
4
- p rq
5
4
  if rq.can_auto_auth?
6
5
  rq.params[ConsoleUtils.token_param] ||= ConsoleUtils.default_token.presence || ConsoleUtils.auto_token_for(rq.uid)
7
6
  end
@@ -4,12 +4,15 @@ module ConsoleUtils::RequestUtils #:nodoc:
4
4
  class Exap < Requester
5
5
  INSPECT_FORMAT = "<Local: %s (%s)>".freeze
6
6
 
7
- ConsoleUtils.request_methods.each do |reqm|
8
- define_method(reqm) do |*args|
9
- @url, *@_args = args
10
- app.public_send(reqm, @url, *normalize_args)
11
- self
12
- end
7
+ ConsoleUtils.request_methods.each do |request_method|
8
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
9
+ def #{request_method}(url, *args)
10
+ @url = url
11
+ @_args = args
12
+ app.process(:#{request_method}, @url, **normalize_args.to_h)
13
+ self
14
+ end
15
+ RUBY
13
16
  end
14
17
 
15
18
  def to_s
@@ -1,21 +1,25 @@
1
1
  require 'uri'
2
- require "console_utils/request_utils/requester"
2
+ require 'open3'
3
+ require 'shellwords'
4
+ require 'console_utils/request_utils/requester'
3
5
 
4
6
  module ConsoleUtils::RequestUtils #:nodoc:
5
7
  class Remo < Requester
6
- OUT_FORMAT = "\n%{size_download}\n%{time_total}".freeze
7
8
  INSPECT_FORMAT = "<Remote: %s in %s ms>".freeze
8
9
  INSPECT_NOTHING = "<Remote: nothing>".freeze
9
10
 
10
11
  attr_reader :request_method
11
12
 
12
- ConsoleUtils.request_methods.each do |reqm|
13
- define_method(reqm) do |url, *args|
14
- @_args = args
15
- @url = urlify(url, *normalize_args)
16
- @request_method = reqm.to_s.upcase
17
- perform
18
- end
13
+ ConsoleUtils.request_methods.each do |request_method|
14
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
15
+ def #{request_method}(url, *args)
16
+ @_args = args
17
+ @request_method = "#{request_method.to_s.upcase}"
18
+ @request_params = normalize_args
19
+ @url = urlify(url, @request_params.params)
20
+ perform
21
+ end
22
+ RUBY
19
23
  end
20
24
 
21
25
  def inspect
@@ -30,30 +34,125 @@ module ConsoleUtils::RequestUtils #:nodoc:
30
34
  @_body
31
35
  end
32
36
 
37
+ attr_reader :_result
38
+
33
39
  protected
34
40
 
35
41
  def perform
36
- IO.popen(curl_command, "r+") { |io| set_payload!(io.readlines) }
42
+ data = @request_params.params.to_json unless params_to_query?
43
+ Curl.(request_method, url, data: data, headers: @request_params.headers) do |result, payload|
44
+ @_result = result
45
+ set_payload!(payload)
46
+ end
37
47
  end
38
48
 
39
49
  private
40
50
 
41
- def set_payload!((*body_lines, size, time))
51
+ def set_payload!((*body_lines, code, time, size))
42
52
  @_body = body_lines.join
53
+ @_code = code.to_i
43
54
  @_size = size.to_f
44
55
  @_time = time.tr(?,, ?.).to_f
45
56
  self
46
57
  end
47
58
 
48
- def curl_command
49
- %W(#{ConsoleUtils.curl_bin} --silent --write-out #{OUT_FORMAT} -X #{request_method} #{url}).
50
- tap { |cmd| puts "# #{cmd.shelljoin.inspect}" unless ConsoleUtils.curl_silence }
59
+ def urlify(path, options = nil)
60
+ URI.join(ConsoleUtils.remote_endpoint, path).
61
+ tap { |uri| uri.query = options.to_query if options && params_to_query? }.to_s
51
62
  end
52
63
 
53
- def urlify(*args)
54
- options = args.extract_options!
55
- URI.join(ConsoleUtils.remote_endpoint, *args).
56
- tap { |uri| uri.query = options.to_query }.to_s
64
+ def params_to_query?
65
+ ["GET", "HEAD"].include?(@request_method) || @request_method.headers["Content-Type"] != "application/json"
66
+ end
67
+
68
+ class Curl
69
+ OUT_FORMAT = '\n%{http_code}\n%{time_total}\n%{size_download}'.freeze
70
+ HEADER_JOIN_PROC = proc { |*kv| ["-H", kv.flatten.join(": ")] }
71
+
72
+ def self.call(*args)
73
+ result = new(*args)
74
+ yield(result.to_h, result.payload)
75
+ end
76
+
77
+ attr_reader :request, :response, :payload
78
+
79
+ def initialize(request_method, url, data: nil, headers: nil)
80
+ cmd = %W(#{ConsoleUtils.curl_bin} --silent -v -g)
81
+ cmd.push("-X#{request_method}")
82
+ cmd.push(url)
83
+
84
+ cmd.concat(headers.flat_map(&HEADER_JOIN_PROC)) if headers.present?
85
+ cmd.push("-d", data) if data.present?
86
+
87
+ cmd_line = Shellwords.join(cmd)
88
+ cmd_line << %( --write-out "#{OUT_FORMAT}")
89
+
90
+ puts "$ #{cmd_line}" if verbose?
91
+
92
+ @response = {}
93
+ @request = {}
94
+ @payload = []
95
+
96
+ Open3.popen3(cmd_line) do |stdin, stdout, stderr, thr|
97
+ # stdin.close
98
+ { stderr: stderr, stdout: stdout }.each do |key, io|
99
+ Thread.new do
100
+ begin
101
+ until (line = io.gets).nil? do
102
+ key == :stderr ? process_stderr(line) : @payload << line
103
+ end
104
+ rescue => e
105
+ warn e
106
+ end
107
+ end
108
+ end
109
+ thr.join
110
+ end
111
+ end
112
+
113
+ KEY_MAP = { ">" => :request, "<" => :response }
114
+
115
+ def process_stderr(line)
116
+ # warn(line)
117
+ if type = KEY_MAP[line.chr]
118
+ line = line[2, line.size-1].strip
119
+
120
+ return if line.size == 0
121
+
122
+ case type
123
+ when :request; set_request(line)
124
+ when :response; set_response(line)
125
+ end
126
+ end
127
+ end
128
+
129
+ def set_request(line)
130
+ # warn("Request: #{line}")
131
+ if !@request.key?(:http_version) && line =~ /^(GET|POST|PUT|PATCH|HEAD|OPTION|DELETE) (.+?) HTTP\/(.+)$/
132
+ @request.merge!(method: $1, url: $2, http_version: $3)
133
+ else
134
+ header, value = line.split(": ", 2)
135
+ @request[header] = value
136
+ end
137
+ end
138
+
139
+ def set_response(line)
140
+ # warn("Response: #{line}")
141
+ if !@response.key?(:http_version) && line =~ /^HTTP\/(.+) (\d+?) (.+)$/
142
+ @response.merge!(http_version: $1, http_code: $2.to_i, http_status: $3)
143
+ else
144
+ header, value = line.split(": ", 2)
145
+ @response[header] = value
146
+ end
147
+ end
148
+
149
+ def to_h
150
+ { response: @response, request: @request }
151
+ end
152
+
153
+ def verbose?
154
+ !ConsoleUtils.curl_silence
155
+ end
57
156
  end
58
157
  end
59
158
  end
@@ -1,29 +1,24 @@
1
- module ConsoleUtils::RequestUtils
2
- class RequestParams
3
- attr_accessor :uid
1
+ # frozen_string_literal: true
4
2
 
5
- def initialize(uid_or_params = true, params = nil, headers = nil)
6
- # puts "Request params: uid_or_params=#{uid_or_params} | params=#{params} | headers=#{headers}"
7
-
8
- if uid_or_params.is_a? Hash
9
- headers, params, uid_or_params = [params, uid_or_params, nil]
10
- end
11
-
12
- @params = params if params
13
- @headers = headers if headers
14
- @uid = auto_auth? && ((uid_or_params.nil? || uid_or_params == true) ? ConsoleUtils.default_uid : uid_or_params)
15
-
16
- ConsoleUtils.logger.debug { "#{uid}, #{params()}, #{headers()}" }
3
+ module ConsoleUtils::RequestUtils
4
+ RequestParams = Struct.new(:params, :headers)
17
5
 
18
- auth_automator.(self)
6
+ class RequestParams
7
+ AutoUid = -> (uid) do
8
+ ConsoleUtils.request_auto_auth && ((uid.nil? || uid == true) ? ConsoleUtils.default_uid : uid)
19
9
  end
20
10
 
21
- def params
22
- @params ||= {}
23
- end
11
+ attr_accessor :uid
24
12
 
25
- def headers
26
- @headers ||= {}
13
+ def initialize(uid = true, *rest, params: nil, headers: nil)
14
+ params, headers = rest if params.nil? && headers.nil? && rest.size > 0
15
+ params, headers, uid = [uid, params, nil] if uid.is_a?(Hash)
16
+ @uid = AutoUid[uid] || uid
17
+ super(params.to_h, headers.to_h)
18
+
19
+ ConsoleUtils.auth_automator.(self) if ConsoleUtils.auth_automator.respond_to?(:call)
20
+ ConsoleUtils.request_hooks.each { |hook| hook.(self) }
21
+ ConsoleUtils.logger.debug { "#{@uid}, #{self}" }
27
22
  end
28
23
 
29
24
  def to_a
@@ -39,21 +34,11 @@ module ConsoleUtils::RequestUtils
39
34
  headers.merge!(default_headers.to_h)
40
35
  end
41
36
 
42
- to_a
37
+ self
43
38
  end
44
39
 
45
40
  def can_auto_auth?
46
- auto_auth? && uid && auth_automator.respond_to?(:call)
47
- end
48
-
49
- private
50
-
51
- def auto_auth?
52
- ConsoleUtils.request_auto_auth
53
- end
54
-
55
- def auth_automator
56
- ConsoleUtils.auth_automator
41
+ ConsoleUtils.request_auto_auth && @uid && ConsoleUtils.auth_automator.respond_to?(:call)
57
42
  end
58
43
  end
59
44
  end
@@ -5,10 +5,8 @@ module ConsoleUtils::RequestUtils #:nodoc:
5
5
  class Requester < SimpleDelegator
6
6
  INFO_HASH_FIELDS = %i(url size time human_size human_time).freeze
7
7
  INFO_FORMAT = "%#-.50{url} | %#10{human_size} | %#10{human_time}\n".freeze
8
- NO_RESPONSE = Term::ANSIColor.red(" \u27A7 Empty response's body.").freeze
9
- PBCOPY_MESSAGE = Term::ANSIColor.green(" \u27A4 Response body copied to pasteboard\n").freeze
10
- COMPLETE_IN = Term::ANSIColor.green("Complete in %s").freeze
11
- TRANSFERED = Term::ANSIColor.cyan("Transfered: %s").freeze
8
+ NO_RESPONSE = ConsoleUtils.pastel.red(" \u27A7 Empty response's body.").freeze
9
+ PBCOPY_MESSAGE = ConsoleUtils.pastel.green(" \u27A4 Response body copied to pasteboard\n").freeze
12
10
 
13
11
  class_attribute :default_params, instance_writer: false
14
12
  attr_reader :url
@@ -54,33 +52,55 @@ module ConsoleUtils::RequestUtils #:nodoc:
54
52
  end
55
53
 
56
54
  def to_info_hash
57
- INFO_HASH_FIELDS.zip(INFO_HASH_FIELDS.map(&method(:public_send))).to_h
55
+ hsh = {}
56
+ INFO_HASH_FIELDS.each { |field| hsh[field] = public_send(field) }
57
+ hsh
58
58
  end
59
59
 
60
60
  protected
61
61
 
62
62
  def normalize_args
63
- RequestParams.new(*@_args).with_default(default_params).tap do |args|
64
- ConsoleUtils.logger.debug { args }
65
- end
63
+ params = RequestParams.new(*@_args).with_default(default_params)
64
+ ConsoleUtils.logger.debug { params.to_a }
65
+ params
66
66
  end
67
67
 
68
68
  private
69
69
 
70
70
  def show_complete_in!(reset = true)
71
71
  return if @_time.nil?
72
- puts "=> #{COMPLETE_IN % [time_ms]}"
72
+ if @_code && status_code = Rack::Utils::HTTP_STATUS_CODES[@_code]
73
+ print "=> ", pastel.public_send(status_color(@_code), "Completed ", pastel.bold("#{@_code} #{status_code}"), " in #{time_ms}"), "\n"
74
+ else
75
+ puts "=> #{pastel.green("Completed in #{time_ms}")}"
76
+ end
77
+ ensure
78
+ @_code = nil
73
79
  @_time = nil
74
80
  end
75
81
 
82
+ def pastel
83
+ ConsoleUtils.pastel
84
+ end
85
+
76
86
  def show_transfered!(reset = true)
77
87
  return if @_size.nil?
78
- puts "=> #{TRANSFERED % [size_downloaded]}"
88
+ print "=> ", pastel.cyan("Transferred: #{size_downloaded}"), "\n"
89
+ ensure
79
90
  @_size = nil
80
91
  end
81
92
 
93
+ def status_color(code)
94
+ case code
95
+ when 200...400; :green
96
+ when 400...500; :red
97
+ when 500...600; :intense_red
98
+ else :yellow
99
+ end
100
+ end
101
+
82
102
  private_constant :PBCOPY_MESSAGE,
83
- :NO_RESPONSE, :COMPLETE_IN, :TRANSFERED,
103
+ :NO_RESPONSE,
84
104
  :INFO_FORMAT
85
105
  end
86
106
  end
@@ -1,3 +1,3 @@
1
1
  module ConsoleUtils
2
- VERSION = "0.6.2"
2
+ VERSION = "0.10.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: console_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-08 00:00:00.000000000 Z
11
+ date: 2020-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,22 +16,22 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.1'
19
+ version: '5.2'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '6'
22
+ version: '7'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '4.1'
29
+ version: '5.2'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '6'
32
+ version: '7'
33
33
  - !ruby/object:Gem::Dependency
34
- name: term-ansicolor
34
+ name: pastel
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
@@ -193,8 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
195
  requirements: []
196
- rubyforge_project:
197
- rubygems_version: 2.6.6
196
+ rubygems_version: 3.0.3
198
197
  signing_key:
199
198
  specification_version: 4
200
199
  summary: Groovy tools for Rails Console.