chupa-text 1.2.0 → 1.2.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
2
  SHA256:
3
- metadata.gz: ae05a44da20490f2d7833d513cfc423819dd65ef5e1d6285e5a82db8482673fa
4
- data.tar.gz: b202c67426ca48058422f169339c069cb6bc42e892a40fd9c72bda3463610b94
3
+ metadata.gz: 99a53085d7eca8e459b0944e44cdb415036d19b6dc5a366e10bc3921a8c8cb09
4
+ data.tar.gz: ce808a0a9e9352e2b4cf92c9e7348b57e522ee1717dc8070631451aa6a3b9a29
5
5
  SHA512:
6
- metadata.gz: 28126643d65dc7ef423dccc0f727be7b275db0005f66f4c40f0c8e5dafe8b159cdea2b6c8aeca98bf7e9979849cf531ddd5afad81f30c85d031dae925029e763
7
- data.tar.gz: 498fb93a26bfd139d9fba1d15d00bbc17547b9e326c403301794b89f2548c78e8d000ed45c3404c3b0a00073e677c1783c64b1423357893c89326d60efeb07d3
6
+ metadata.gz: 334356c90df57f22ae1fe0871e93147470c7505782487f71613f3fa794ea7fe0ed03b16980892beb46d662f830b876b6b4ff5132b8677892be1246ea26e38f40
7
+ data.tar.gz: 86de4013d3f07d4d89c2113d01d78d4e6685b95af28ab1ad72267908d3c4b9ea30720eec515380989b6fb2a50d913041ee8223197cbcfa00c51b61b97506d1d7
@@ -1,5 +1,21 @@
1
1
  # News
2
2
 
3
+ ## 1.2.1: 2019-03-04
4
+
5
+ ### Improvements
6
+
7
+ * `ChupaText::ExternalCommand`:
8
+
9
+ * Added more logs.
10
+
11
+ * Added support for ensuring killing external command.
12
+
13
+ * Added default value API.
14
+
15
+ * `ChupaText::VirtualFileContent`:
16
+
17
+ * Added support for inlining small data.
18
+
3
19
  ## 1.2.0: 2019-03-03
4
20
 
5
21
  ### Improvements
@@ -40,18 +40,9 @@ module ChupaText
40
40
  path_converter = PathConverter.new(entry.full_name,
41
41
  uri_escape: true)
42
42
  entry_uri.path = "#{base_path}/#{path_converter.convert}"
43
- size = entry.header.size
44
- if size < (32 * 1024)
45
- entry_data = Data.new(source_data: data)
46
- entry_data.uri = entry_uri
47
- body = entry.read || ""
48
- entry_data.body = body
49
- entry_data.size = body.bytesize
50
- else
51
- entry_data = VirtualFileData.new(entry_uri,
52
- entry,
53
- :source_data => data)
54
- end
43
+ entry_data = VirtualFileData.new(entry_uri,
44
+ entry,
45
+ :source_data => data)
55
46
  yield(entry_data)
56
47
  end
57
48
  end
@@ -49,18 +49,9 @@ module ChupaText
49
49
  encoding: base_path.encoding,
50
50
  uri_escape: true)
51
51
  entry_uri.path = "#{base_path}/#{path_converter.convert}"
52
- size = entry.raw_data.window_size
53
- if size < (8 * 1024)
54
- entry_data = Data.new(source_data: data)
55
- entry_data.uri = entry_uri
56
- body = entry.file_data.read
57
- entry_data.body = body
58
- entry_data.size = body.bytesize
59
- else
60
- entry_data = VirtualFileData.new(entry_uri,
61
- entry.file_data,
62
- source_data: data)
63
- end
52
+ entry_data = VirtualFileData.new(entry_uri,
53
+ entry.file_data,
54
+ source_data: data)
64
55
  yield(entry_data)
65
56
  end
66
57
  end
@@ -22,6 +22,42 @@ module ChupaText
22
22
  class ExternalCommand
23
23
  include Loggable
24
24
 
25
+ @default_timeout = nil
26
+ @default_limit_cpu = nil
27
+ @default_limit_as = nil
28
+ class << self
29
+ def default_timeout
30
+ @default_timeout || ENV["CHUPA_TEXT_EXTERNAL_COMMAND_TIMEOUT"]
31
+ end
32
+
33
+ def default_timeout=(timeout)
34
+ @default_timeout = timeout
35
+ end
36
+
37
+ def default_limit_cpu
38
+ @default_limit_cpu || limit_env("CPU")
39
+ end
40
+
41
+ def default_limit_cpu=(cpu)
42
+ @default_limit_cpu = cpu
43
+ end
44
+
45
+ def default_limit_as
46
+ @default_limit_as || limit_env("AS")
47
+ end
48
+
49
+ def default_limit_as=(as)
50
+ @default_limit_as = as
51
+ end
52
+
53
+ private
54
+ def limit_env(name)
55
+ ENV["CHUPA_TEXT_EXTERNAL_COMMAND_LIMIT_#{name}"] ||
56
+ # For backward compatibility
57
+ ENV["CHUPA_EXTERNAL_COMMAND_LIMIT_#{name}"]
58
+ end
59
+ end
60
+
25
61
  attr_reader :path
26
62
  def initialize(path)
27
63
  @path = Pathname.new(path)
@@ -37,7 +73,18 @@ module ChupaText
37
73
  @path.to_s,
38
74
  *arguments,
39
75
  spawn_options(options[:spawn_options]))
40
- status = wait_process(pid, options[:timeout])
76
+ status = nil
77
+ begin
78
+ status = wait_process(pid, options[:timeout])
79
+ ensure
80
+ unless status
81
+ begin
82
+ Process.kill(:KILL, pid)
83
+ Process.waitpid(pid)
84
+ rescue SystemCallError
85
+ end
86
+ end
87
+ end
41
88
  status.success?
42
89
  end
43
90
 
@@ -72,11 +119,8 @@ module ChupaText
72
119
  return if options[option_key]
73
120
 
74
121
  tag = "[limit][#{key}]"
75
- value =
76
- ENV["CHUPA_TEXT_EXTERNAL_COMMAND_LIMIT_#{key.to_s.upcase}"] ||
77
- # For backward compatibility
78
- ENV["CHUPA_EXTERNAL_COMMAND_LIMIT_#{key.to_s.upcase}"]
79
- value = send("parse_#{type}", tag, value)
122
+ value = self.class.__send__("default_limit_#{key}")
123
+ value = __send__("parse_#{type}", tag, value)
80
124
  return if value.nil?
81
125
  rlimit_number = Process.const_get("RLIMIT_#{key.to_s.upcase}")
82
126
  soft_limit, hard_limit = Process.getrlimit(rlimit_number)
@@ -96,67 +140,87 @@ module ChupaText
96
140
  end
97
141
 
98
142
  def parse_int(tag, value)
99
- return nil if value.nil?
100
- return nil if value.empty?
101
- begin
102
- Integer(value)
103
- rescue ArgumentError
104
- log_invalid_value(tag, value, type, "int")
143
+ case value
144
+ when nil
105
145
  nil
146
+ when Integer
147
+ value
148
+ when Float
149
+ value.round
150
+ else
151
+ return nil if value.empty?
152
+ begin
153
+ Integer(value)
154
+ rescue ArgumentError
155
+ log_invalid_value(tag, value, type, "int")
156
+ nil
157
+ end
106
158
  end
107
159
  end
108
160
 
109
161
  def parse_size(tag, value)
110
- return nil if value.nil?
111
- return nil if value.empty?
112
- scale = 1
113
162
  case value
114
- when /GB?\z/i
115
- scale = 1024 ** 3
116
- number = $PREMATCH
117
- when /MB?\z/i
118
- scale = 1024 ** 2
119
- number = $PREMATCH
120
- when /KB?\z/i
121
- scale = 1024 ** 1
122
- number = $PREMATCH
123
- when /B?\z/i
124
- number = $PREMATCH
163
+ when nil
164
+ nil
165
+ when Numeric
166
+ value
125
167
  else
126
- number = value
127
- end
128
- begin
129
- number = Float(number)
130
- rescue ArgumentError
131
- log_invalid_value(tag, value, "size")
132
- return nil
168
+ return nil if value.empty?
169
+ scale = 1
170
+ case value
171
+ when /GB?\z/i
172
+ scale = 1024 ** 3
173
+ number = $PREMATCH
174
+ when /MB?\z/i
175
+ scale = 1024 ** 2
176
+ number = $PREMATCH
177
+ when /KB?\z/i
178
+ scale = 1024 ** 1
179
+ number = $PREMATCH
180
+ when /B?\z/i
181
+ number = $PREMATCH
182
+ else
183
+ number = value
184
+ end
185
+ begin
186
+ number = Float(number)
187
+ rescue ArgumentError
188
+ log_invalid_value(tag, value, "size")
189
+ return nil
190
+ end
191
+ (number * scale).to_i
133
192
  end
134
- (number * scale).to_i
135
193
  end
136
194
 
137
195
  def parse_time(tag, value)
138
- return nil if value.nil?
139
- return nil if value.empty?
140
- scale = 1
141
196
  case value
142
- when /h\z/i
143
- scale = 60 * 60
144
- number = $PREMATCH
145
- when /m\z/i
146
- scale = 60
147
- number = $PREMATCH
148
- when /s\z/i
149
- number = $PREMATCH
197
+ when nil
198
+ nil
199
+ when Numeric
200
+ value
150
201
  else
151
- number = value
152
- end
153
- begin
154
- number = Float(number)
155
- rescue ArgumentError
156
- log_invalid_value(tag, value, "time")
157
- return nil
202
+ return nil if value.empty?
203
+ scale = 1
204
+ case value
205
+ when /h\z/i
206
+ scale = 60 * 60
207
+ number = $PREMATCH
208
+ when /m\z/i
209
+ scale = 60
210
+ number = $PREMATCH
211
+ when /s\z/i
212
+ number = $PREMATCH
213
+ else
214
+ number = value
215
+ end
216
+ begin
217
+ number = Float(number)
218
+ rescue ArgumentError
219
+ log_invalid_value(tag, value, "time")
220
+ return nil
221
+ end
222
+ (number * scale).to_f
158
223
  end
159
- (number * scale).to_f
160
224
  end
161
225
 
162
226
  def log_invalid_value(tag, value, type)
@@ -164,17 +228,17 @@ module ChupaText
164
228
  end
165
229
 
166
230
  def wait_process(pid, timeout)
167
- if timeout.nil?
168
- timeout_env = ENV["CHUPA_TEXT_EXTERNAL_COMMAND_TIMEOUT"]
169
- timeout = parse_time("[timeout]", timeout_env) if timeout_env
170
- end
171
-
231
+ tag = "[timeout]"
232
+ timeout = parse_time(tag, timeout || self.class.default_timeout)
172
233
  if timeout
234
+ info("#{log_tag}#{tag}[use] <#{timeout}s>: <#{pid}>")
173
235
  status = wait_process_timeout(pid, timeout)
174
236
  return status if status
237
+ info("#{log_tag}#{tag}[terminate] <#{pid}>")
175
238
  Process.kill(:TERM, pid)
176
239
  status = wait_process_timeout(pid, 5)
177
240
  return status if status
241
+ info("#{log_tag}#{tag}[kill] <#{pid}>")
178
242
  Process.kill(:KILL, pid)
179
243
  end
180
244
  _, status = Process.waitpid2(pid)
@@ -15,5 +15,5 @@
15
15
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
  module ChupaText
18
- VERSION = "1.2.0"
18
+ VERSION = "1.2.1"
19
19
  end
@@ -20,12 +20,10 @@ require "tempfile"
20
20
 
21
21
  module ChupaText
22
22
  class VirtualContent
23
- KILO_BYTE = 1024
24
- BUFFER_SIZE = 64 * KILO_BYTE
23
+ INLINE_MAX_SIZE = 64 * 1024
25
24
 
26
25
  attr_reader :size
27
26
  def initialize(input, original_path=nil)
28
- @file = nil
29
27
  if original_path.is_a?(String)
30
28
  if original_path.empty?
31
29
  original_path = nil
@@ -34,28 +32,56 @@ module ChupaText
34
32
  end
35
33
  end
36
34
  @original_path = original_path
37
- setup_file do |file|
38
- @size = IO.copy_stream(input, file)
35
+ body = input.read(INLINE_MAX_SIZE + 1) || ""
36
+ if body.bytesize <= INLINE_MAX_SIZE
37
+ @body = body
38
+ @size = @body.bytesize
39
+ @file = nil
40
+ @path = nil
41
+ else
42
+ @body = nil
43
+ setup_file do |file|
44
+ file.write(body)
45
+ @size = body.bytesize
46
+ @size += IO.copy_stream(input, file)
47
+ end
39
48
  end
40
49
  end
41
50
 
42
51
  def open(&block)
43
- File.open(path, "rb", &block)
52
+ if @body
53
+ yield(StringIO.new(@body))
54
+ else
55
+ File.open(path, "rb", &block)
56
+ end
44
57
  end
45
58
 
46
59
  def body
47
- open do |file|
48
- file.read
60
+ if @body
61
+ @body
62
+ else
63
+ open do |file|
64
+ file.read
65
+ end
49
66
  end
50
67
  end
51
68
 
52
69
  def peek_body(size)
53
- open do |file|
54
- file.read(size)
70
+ if @body
71
+ @body[0, size]
72
+ else
73
+ open do |file|
74
+ file.read(size)
75
+ end
55
76
  end
56
77
  end
57
78
 
58
79
  def path
80
+ if @path.nil?
81
+ setup_file do |file|
82
+ file.write(@body)
83
+ end
84
+ end
59
85
  @path
60
86
  end
61
87
 
@@ -77,6 +103,7 @@ module ChupaText
77
103
  def setup_file
78
104
  basename = compute_tempfile_basename
79
105
  @file = Tempfile.new(basename)
106
+ @file.binmode
80
107
  @path = @file.path
81
108
  yield(@file)
82
109
  @file.close
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2013-2019 Kouhei Sutou <kou@clear-code.com>
2
2
  #
3
3
  # This library is free software; you can redistribute it and/or
4
4
  # modify it under the terms of the GNU Lesser General Public
@@ -53,7 +53,7 @@ class TestVirtualContent < Test::Unit::TestCase
53
53
 
54
54
  sub_test_case("large data") do
55
55
  def setup
56
- @body = "X" * (ChupaText::VirtualContent::BUFFER_SIZE + 1)
56
+ @body = "X" * (ChupaText::VirtualContent::INLINE_MAX_SIZE + 1)
57
57
  end
58
58
 
59
59
  def test_size
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chupa-text
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kouhei Sutou
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-02 00:00:00.000000000 Z
11
+ date: 2019-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: archive-zip