lokalise_manager 1.2.1 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33815f129df22f7a27f91689cad944193aca9b992f14e7115a2737088785d3b3
4
- data.tar.gz: 1fc5a893bb917bac5afd39f2b35dbbb54286b878dce42f0805135105490520b5
3
+ metadata.gz: 0f9ca0fe8caf151e84dcc09f29368bc61b5bc3cdb4341ef5c1b21040b764a17a
4
+ data.tar.gz: 8c9194a836a1261638f2b22d8d2d7553bfbe605325911cb0c0ecef9332e9084c
5
5
  SHA512:
6
- metadata.gz: 7fecf43ac4f105be85fe2e4548643849b78a239ec523a79b37fec4b6acbeddf319dd4ac594e5caf28e4b174fed76e05b18d3bf6d6343d055daa2115d661b41c4
7
- data.tar.gz: 85f6c703a1ee2107cfe165b7c652cc81d2c2f0a0ae2a02af44cfb0e0cf31a185e5cbe3cbe27c8c53d411a8dd4f3046a98b02dadde3d983855e02cead3347cfb4
6
+ metadata.gz: 7c4b7131ea9d6b60ff4094d0e34c92484818eb3c608a016932426c83bbcab4a06f4c820399f2fa70cc2a78d9a60a73dcf442ec9ba082bdc095ab539b467e1677
7
+ data.tar.gz: b98c062b4ecc030c37fa1f1ad95126209749c99ec7aba72b616fad380819d55552dc6d4b2a611b94471f79b3748855eefbaab3c9397ab49e9f8e19a6a6afb1ab
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.0 (27-Jan-22)
4
+
5
+ * `export!` method is now taking advantage of multi-threading (as Lokalise API allows to send requests in parallel since January 2022)
6
+ * Test with Ruby 3.1.0
7
+ * Other minor fixes
8
+
3
9
  ## 1.2.1 (26-Nov-21)
4
10
 
5
11
  * Use refinements instead of monkey patching to add hash methods
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # LokaliseManager
2
2
 
3
3
  ![Gem](https://img.shields.io/gem/v/lokalise_manager)
4
- [![Build Status](https://travis-ci.com/bodrovis/lokalise_manager.svg?branch=master)](https://travis-ci.com/github/bodrovis/lokalise_manager)
4
+ ![CI](https://github.com/bodrovis/lokalise_manager/actions/workflows/ci.yml/badge.svg)
5
5
  [![Test Coverage](https://codecov.io/gh/bodrovis/lokalise_manager/graph/badge.svg)](https://codecov.io/gh/bodrovis/lokalise_manager)
6
6
  ![Downloads total](https://img.shields.io/gem/dt/lokalise_manager)
7
7
 
@@ -271,4 +271,4 @@ importer.import!
271
271
 
272
272
  ## License
273
273
 
274
- Copyright (c) [Lokalise team](http://lokalise.com), [Ilya Bodrov](http://bodrovis.tech). License type is [MIT](https://github.com/bodrovis/lokalise_manager/blob/master/LICENSE).
274
+ Copyright (c) [Lokalise team](http://lokalise.com), [Ilya Bodrov](http://bodrovis.tech). License type is [MIT](https://github.com/bodrovis/lokalise_manager/blob/master/LICENSE).
@@ -38,12 +38,13 @@ module LokaliseManager
38
38
  client_opts = [config.api_token, {enable_compression: true}.merge(config.timeouts)]
39
39
  client_method = config.use_oauth2_token ? :oauth_client : :client
40
40
 
41
- @api_client ||= ::Lokalise.send(client_method, *client_opts)
41
+ @api_client = ::Lokalise.send(client_method, *client_opts)
42
42
  end
43
43
 
44
44
  # Resets API client
45
45
  def reset_api_client!
46
- Lokalise.reset_client!
46
+ ::Lokalise.reset_client!
47
+ ::Lokalise.reset_oauth_client!
47
48
  @api_client = nil
48
49
  end
49
50
 
@@ -5,6 +5,7 @@ require 'base64'
5
5
  module LokaliseManager
6
6
  module TaskDefinitions
7
7
  class Exporter < Base
8
+ using LokaliseManager::Utils::ArrayUtils
8
9
  # Performs translation file export to Lokalise and returns an array of queued processes
9
10
  #
10
11
  # @return [Array]
@@ -12,10 +13,13 @@ module LokaliseManager
12
13
  check_options_errors!
13
14
 
14
15
  queued_processes = []
15
- each_file do |full_path, relative_path|
16
- queued_processes << do_upload(full_path, relative_path)
17
- rescue StandardError => e
18
- raise e.class, "Error while trying to upload #{full_path}: #{e.message}"
16
+
17
+ all_files.in_groups_of(6) do |files_group|
18
+ parallel_upload(files_group).each do |thr|
19
+ raise_on_fail thr
20
+
21
+ queued_processes.push thr[:process]
22
+ end
19
23
  end
20
24
 
21
25
  $stdout.print('Task complete!') unless config.silent_mode
@@ -25,18 +29,32 @@ module LokaliseManager
25
29
 
26
30
  private
27
31
 
32
+ def parallel_upload(files_group)
33
+ files_group.compact.map do |file_data|
34
+ do_upload(*file_data)
35
+ end.map(&:value)
36
+ end
37
+
38
+ def raise_on_fail(thread)
39
+ raise thread[:error].class, "Error while trying to upload #{thread[:path]}: #{thread[:error].message}" if thread[:status] == :fail
40
+ end
41
+
28
42
  # Performs the actual file uploading to Lokalise. If the API rate limit is exceeed,
29
43
  # applies exponential backoff
30
44
  def do_upload(f_path, r_path)
31
- with_exp_backoff(config.max_retries_export) do
32
- api_client.upload_file project_id_with_branch, opts(f_path, r_path)
45
+ Thread.new do
46
+ process = with_exp_backoff(config.max_retries_export) do
47
+ api_client.upload_file project_id_with_branch, opts(f_path, r_path)
48
+ end
49
+ {status: :ok, process: process}
50
+ rescue StandardError => e
51
+ {status: :fail, path: f_path, error: e}
33
52
  end
34
53
  end
35
54
 
36
- # Processes each translation file in the specified directory
37
- def each_file
38
- return unless block_given?
39
-
55
+ # Gets translation files from the specified directory
56
+ def all_files
57
+ files = []
40
58
  loc_path = config.locales_path
41
59
  Dir["#{loc_path}/**/*"].sort.each do |f|
42
60
  full_path = Pathname.new f
@@ -45,8 +63,9 @@ module LokaliseManager
45
63
 
46
64
  relative_path = full_path.relative_path_from Pathname.new(loc_path)
47
65
 
48
- yield full_path, relative_path
66
+ files << [full_path, relative_path]
49
67
  end
68
+ files
50
69
  end
51
70
 
52
71
  # Generates export options
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Taken from https://github.com/rails/rails/blob/6bfc637659248df5d6719a86d2981b52662d9b50/activesupport/lib/active_support/core_ext/array/grouping.rb
4
+
5
+ module LokaliseManager
6
+ module Utils
7
+ module ArrayUtils
8
+ refine Array do
9
+ def in_groups_of(number, fill_with = nil, &block)
10
+ if number.to_i <= 0
11
+ raise ArgumentError,
12
+ "Group size must be a positive integer, was #{number.inspect}"
13
+ end
14
+
15
+ if fill_with == false
16
+ collection = self
17
+ else
18
+ padding = (number - (size % number)) % number
19
+ collection = dup.concat(Array.new(padding, fill_with))
20
+ end
21
+
22
+ collection.each_slice(number, &block)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LokaliseManager
4
- VERSION = '1.2.1'
4
+ VERSION = '2.0.0'
5
5
  end
@@ -3,6 +3,7 @@
3
3
  require 'yaml'
4
4
 
5
5
  require 'lokalise_manager/utils/hash_utils'
6
+ require 'lokalise_manager/utils/array_utils'
6
7
 
7
8
  require 'lokalise_manager/version'
8
9
  require 'lokalise_manager/error'
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency 'rspec', '~> 3.6'
33
33
  spec.add_development_dependency 'rubocop', '~> 1.0'
34
34
  spec.add_development_dependency 'rubocop-performance', '~> 1.5'
35
- spec.add_development_dependency 'rubocop-rspec', '~> 2.6.0'
35
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.6'
36
36
  spec.add_development_dependency 'simplecov', '~> 0.16'
37
37
  spec.add_development_dependency 'vcr', '~> 6.0'
38
38
  spec.metadata = {
@@ -24,7 +24,7 @@ describe LokaliseManager::TaskDefinitions::Base do
24
24
  specify '.reset_client!' do
25
25
  expect(described_object.api_client).to be_an_instance_of(Lokalise::Client)
26
26
  described_object.reset_api_client!
27
- current_client = described_object.instance_variable_get '@api_client'
27
+ current_client = described_object.instance_variable_get :@api_client
28
28
  expect(current_client).to be_nil
29
29
  end
30
30
 
@@ -35,17 +35,19 @@ describe LokaliseManager::TaskDefinitions::Exporter do
35
35
  end
36
36
 
37
37
  it 'handles too many requests' do
38
+ allow(described_object.config).to receive(:max_retries_export).and_return(1)
38
39
  allow(described_object).to receive(:sleep).and_return(0)
39
40
 
40
41
  fake_client = instance_double('Lokalise::Client')
42
+ allow(fake_client).to receive(:token).with(any_args).and_return('fake_token')
41
43
  allow(fake_client).to receive(:upload_file).with(any_args).and_raise(Lokalise::Error::TooManyRequests)
42
44
  allow(described_object).to receive(:api_client).and_return(fake_client)
43
45
 
44
- expect(-> { described_object.export! }).to raise_error(Lokalise::Error::TooManyRequests, /Gave up after 2 retries/i)
46
+ expect(-> { described_object.export! }).to raise_error(Lokalise::Error::TooManyRequests, /Gave up after 1 retries/i)
45
47
 
46
- expect(described_object).to have_received(:sleep).exactly(2).times
47
- expect(described_object).to have_received(:api_client).exactly(3).times
48
- expect(fake_client).to have_received(:upload_file).exactly(3).times
48
+ expect(described_object).to have_received(:sleep).exactly(6).times
49
+ expect(described_object).to have_received(:api_client).at_least(12).times
50
+ expect(fake_client).to have_received(:upload_file).exactly(12).times
49
51
  end
50
52
  end
51
53
  end
@@ -108,9 +110,9 @@ describe LokaliseManager::TaskDefinitions::Exporter do
108
110
  end
109
111
  end
110
112
 
111
- describe '.each_file' do
113
+ describe '#all_files' do
112
114
  it 'yield proper arguments' do
113
- expect { |b| described_object.send(:each_file, &b) }.to yield_with_args(
115
+ expect(described_object.send(:all_files).first).to include(
114
116
  Pathname.new(path),
115
117
  Pathname.new(relative_name)
116
118
  )
@@ -180,30 +182,29 @@ describe LokaliseManager::TaskDefinitions::Exporter do
180
182
  end
181
183
  end
182
184
 
183
- describe '.each_file' do
184
- it 'yields every translation file' do
185
- expect { |b| described_object.send(:each_file, &b) }.to yield_successive_args(
186
- [
187
- Pathname.new(path),
188
- Pathname.new(relative_name)
189
- ],
190
- [
191
- Pathname.new(path_ru),
192
- Pathname.new(filename_ru)
193
- ]
185
+ describe '#each_file' do
186
+ it 'returns all files' do
187
+ files = described_object.send(:all_files)
188
+ expect(files[0]).to include(
189
+ Pathname.new(path),
190
+ Pathname.new(relative_name)
191
+ )
192
+ expect(files[1]).to include(
193
+ Pathname.new(path_ru),
194
+ Pathname.new(filename_ru)
194
195
  )
195
196
  end
196
197
 
197
- it 'does not yield files that have to be skipped' do
198
+ it 'does not return files that have to be skipped' do
198
199
  allow(described_object.config).to receive(:skip_file_export).twice.and_return(
199
200
  ->(f) { f.split[1].to_s.include?('ru') }
200
201
  )
201
- expect { |b| described_object.send(:each_file, &b) }.to yield_successive_args(
202
- [
203
- Pathname.new(path),
204
- Pathname.new(relative_name)
205
- ]
202
+ files = described_object.send(:all_files)
203
+ expect(files[0]).to include(
204
+ Pathname.new(path),
205
+ Pathname.new(relative_name)
206
206
  )
207
+ expect(files.count).to eq(1)
207
208
 
208
209
  expect(described_object.config).to have_received(:skip_file_export).twice
209
210
  end
@@ -9,12 +9,16 @@ describe LokaliseManager::TaskDefinitions::Importer do
9
9
  let(:loc_path) { described_object.config.locales_path }
10
10
  let(:project_id) { ENV['LOKALISE_PROJECT_ID'] }
11
11
  let(:local_trans) { "#{Dir.getwd}/spec/fixtures/trans.zip" }
12
- let(:faulty_trans) { "#{Dir.getwd}/spec/fixtures/faulty_trans.zip" }
13
12
 
14
- describe '.open_and_process_zip' do
13
+ describe '#open_and_process_zip' do
15
14
  it 're-raises errors during file processing' do
16
- expect(-> { described_object.send(:open_and_process_zip, faulty_trans) }).
17
- to raise_error(Psych::DisallowedClass, /Error when trying to process fail\.yml/)
15
+ entry = double
16
+ allow(entry).to receive(:name).and_return('fail.yml')
17
+ allow(described_object).to receive(:data_from).with(entry).and_raise(EncodingError)
18
+ expect(-> { described_object.send(:process!, entry) }).
19
+ to raise_error(EncodingError, /Error when trying to process fail\.yml/)
20
+
21
+ expect(described_object).to have_received(:data_from)
18
22
  end
19
23
 
20
24
  it 're-raises errors during file opening' do
@@ -23,7 +27,7 @@ describe LokaliseManager::TaskDefinitions::Importer do
23
27
  end
24
28
  end
25
29
 
26
- describe '.download_files' do
30
+ describe '#download_files' do
27
31
  it 'returns a proper download URL' do
28
32
  response = VCR.use_cassette('download_files') do
29
33
  described_object.send :download_files
@@ -111,9 +115,9 @@ describe LokaliseManager::TaskDefinitions::Importer do
111
115
 
112
116
  expect(result).to be true
113
117
 
114
- expect(count_translations).to eq(8)
115
- expect_file_exist loc_path, 'en.yml'
116
- expect_file_exist loc_path, 'ru.yml'
118
+ expect(count_translations).to eq(24)
119
+ expect_file_exist loc_path, 'en_1.yml'
120
+ expect_file_exist loc_path, 'ru_2.yml'
117
121
  end
118
122
 
119
123
  it 'runs import successfully but does not provide any output when silent_mode is enabled' do
@@ -125,8 +129,8 @@ describe LokaliseManager::TaskDefinitions::Importer do
125
129
  end
126
130
 
127
131
  expect(result).to be true
128
- expect_file_exist loc_path, 'en.yml'
129
- expect_file_exist loc_path, 'ru.yml'
132
+ expect_file_exist loc_path, 'en_1.yml'
133
+ expect_file_exist loc_path, 'ru_2.yml'
130
134
  expect(described_object.config).to have_received(:silent_mode).at_most(1).times
131
135
  end
132
136
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe LokaliseManager::Utils::ArrayUtils do
4
+ using described_class
5
+ let(:arr) { (1..8).to_a }
6
+
7
+ describe '#in_groups_of' do
8
+ it 'raises an exception when the number is less than 1' do
9
+ expect(-> { arr.in_groups_of(-1) }).to raise_error(ArgumentError)
10
+ end
11
+
12
+ it 'uses collection itself if fill_with is false' do
13
+ enum = arr.in_groups_of(5, false)
14
+ enum.next
15
+ expect(enum.next.count).to eq(3)
16
+ end
17
+ end
18
+ end
data/spec/support/vcr.rb CHANGED
@@ -6,6 +6,8 @@ VCR.configure do |c|
6
6
  c.ignore_hosts 'codeclimate.com'
7
7
  c.hook_into :faraday
8
8
  c.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'vcr_cassettes')
9
- c.filter_sensitive_data('<LOKALISE_TOKEN>') { ENV.fetch('LOKALISE_API_TOKEN') }
9
+ c.filter_sensitive_data('<LOKALISE_TOKEN>') do |_i|
10
+ ENV.fetch('LOKALISE_API_TOKEN')
11
+ end
10
12
  c.configure_rspec_metadata!
11
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lokalise_manager
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ilya Bodrov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-26 00:00:00.000000000 Z
11
+ date: 2022-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-lokalise-api
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 2.6.0
131
+ version: '2.6'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 2.6.0
138
+ version: '2.6'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: simplecov
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -187,6 +187,7 @@ files:
187
187
  - lib/lokalise_manager/task_definitions/base.rb
188
188
  - lib/lokalise_manager/task_definitions/exporter.rb
189
189
  - lib/lokalise_manager/task_definitions/importer.rb
190
+ - lib/lokalise_manager/utils/array_utils.rb
190
191
  - lib/lokalise_manager/utils/hash_utils.rb
191
192
  - lib/lokalise_manager/version.rb
192
193
  - lokalise_manager.gemspec
@@ -195,6 +196,7 @@ files:
195
196
  - spec/lib/lokalise_manager/task_definitions/exporter_spec.rb
196
197
  - spec/lib/lokalise_manager/task_definitions/importer_spec.rb
197
198
  - spec/lib/lokalise_manager_spec.rb
199
+ - spec/lib/utils/array_utils_spec.rb
198
200
  - spec/lib/utils/hash_utils_spec.rb
199
201
  - spec/spec_helper.rb
200
202
  - spec/support/file_manager.rb
@@ -220,7 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
220
222
  - !ruby/object:Gem::Version
221
223
  version: '0'
222
224
  requirements: []
223
- rubygems_version: 3.2.31
225
+ rubygems_version: 3.3.5
224
226
  signing_key:
225
227
  specification_version: 4
226
228
  summary: Lokalise integration for Ruby
@@ -230,6 +232,7 @@ test_files:
230
232
  - spec/lib/lokalise_manager/task_definitions/exporter_spec.rb
231
233
  - spec/lib/lokalise_manager/task_definitions/importer_spec.rb
232
234
  - spec/lib/lokalise_manager_spec.rb
235
+ - spec/lib/utils/array_utils_spec.rb
233
236
  - spec/lib/utils/hash_utils_spec.rb
234
237
  - spec/spec_helper.rb
235
238
  - spec/support/file_manager.rb