turbotlib 0.0.9 → 0.0.10
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 +7 -0
- data/.gitignore +8 -0
- data/.rspec +3 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/README.md +14 -0
- data/Rakefile +16 -0
- data/lib/turbotlib.rb +44 -16
- data/lib/turbotlib/client.rb +26 -0
- data/lib/turbotlib/ftp.rb +109 -0
- data/lib/turbotlib/logger.rb +15 -0
- data/lib/turbotlib/processor.rb +30 -0
- data/lib/turbotlib/version.rb +1 -1
- data/spec/spec_helper.rb +16 -0
- data/spec/turbotlib/ftp_spec.rb +78 -0
- data/spec/turbotlib/logger_spec.rb +18 -0
- data/spec/turbotlib/processor_spec.rb +50 -0
- data/spec/turbotlib_spec.rb +44 -44
- data/turbotlib.gemspec +30 -0
- metadata +147 -19
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 44b9719707388531d6f0172d1c78543924e006c9
|
4
|
+
data.tar.gz: 9161d47bfc1d216523b72d3ee4e422b21cb6ef70
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 357630b07308d9b1a0b2a0f43449ed30bd615240a5f556012665092bea59b34b27c0894d5be432bae272d5cda3467b86d098f9f582fce2514942761997b48a8b
|
7
|
+
data.tar.gz: 398fae55cf3c0a85577ba2624c2a82ecb3a007d3f20c5e604871bc4ef2b40c6af8f13fc90baf80062a0ce7cc52518d975376c19fbe3570268adf97e5b2eb2994
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# turbotlib-ruby
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/turbotlib)
|
4
|
+
[](https://travis-ci.org/openc/turbotlib-ruby)
|
5
|
+
[](https://gemnasium.com/openc/turbotlib-ruby)
|
6
|
+
[](https://coveralls.io/r/openc/turbotlib-ruby)
|
7
|
+
[](https://codeclimate.com/github/openc/turbotlib-ruby)
|
8
|
+
|
9
|
+
## Releasing a new version
|
10
|
+
|
11
|
+
Bump the version in `lib/turbotlib/version.rb` according to the [Semantic Versioning](http://semver.org/) convention, then:
|
12
|
+
|
13
|
+
git commit lib/turbotlib/version.rb -m 'Release new version'
|
14
|
+
rake release # requires Rubygems credentials
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
task :default => :spec
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'yard'
|
11
|
+
YARD::Rake::YardocTask.new
|
12
|
+
rescue LoadError
|
13
|
+
task :yard do
|
14
|
+
abort 'YARD is not available. In order to run yard, you must: gem install yard'
|
15
|
+
end
|
16
|
+
end
|
data/lib/turbotlib.rb
CHANGED
@@ -1,26 +1,48 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'forwardable'
|
1
3
|
require 'yaml'
|
4
|
+
|
2
5
|
require 'scraperwiki'
|
3
6
|
|
7
|
+
require 'turbotlib/logger'
|
8
|
+
require 'turbotlib/client'
|
9
|
+
require 'turbotlib/ftp'
|
10
|
+
require 'turbotlib/processor'
|
11
|
+
|
4
12
|
class Turbotlib
|
5
13
|
class << self
|
6
14
|
include ScraperWiki
|
7
15
|
|
16
|
+
# Logs a message to STDERR.
|
17
|
+
#
|
18
|
+
# @param [String] message a log message
|
8
19
|
def log(message)
|
9
20
|
$stderr.puts message
|
10
21
|
end
|
11
22
|
|
23
|
+
# Returns the path to the data directory.
|
24
|
+
#
|
25
|
+
# @return [String] the path to the data directory
|
12
26
|
def data_dir
|
13
|
-
path_to(
|
27
|
+
path_to('data')
|
14
28
|
end
|
15
29
|
|
30
|
+
# Returns the path to the sources directory.
|
31
|
+
#
|
32
|
+
# @return [String] the path to the sources directory
|
16
33
|
def sources_dir
|
17
34
|
if in_production? && !is_admin?
|
18
|
-
raise
|
35
|
+
raise 'Only admins are permitted to write to `sources_dir`'
|
19
36
|
else
|
20
|
-
path_to(
|
37
|
+
path_to('sources')
|
21
38
|
end
|
22
39
|
end
|
23
40
|
|
41
|
+
# Saves and returns the value of a variable.
|
42
|
+
#
|
43
|
+
# @param [String] a variable name
|
44
|
+
# @param val the value of the variable
|
45
|
+
# @return the value of the variable
|
24
46
|
def save_var(key, val)
|
25
47
|
vars = get_vars
|
26
48
|
vars[key] = val
|
@@ -28,23 +50,33 @@ class Turbotlib
|
|
28
50
|
val
|
29
51
|
end
|
30
52
|
|
53
|
+
# Returns the value of a variable.
|
54
|
+
#
|
55
|
+
# @param [String] a variable name
|
56
|
+
# @return the value of the variable
|
31
57
|
def get_var(key)
|
32
58
|
get_vars[key]
|
33
59
|
end
|
34
60
|
|
35
|
-
# Override default in ScraperWiki gem
|
61
|
+
# Override default in ScraperWiki gem.
|
62
|
+
#
|
63
|
+
# @return [SqliteMagic::Connection] a SQLite connection
|
36
64
|
def sqlite_magic_connection
|
37
65
|
db = "#{data_dir}/data.sqlite"
|
38
66
|
@sqlite_magic_connection ||= SqliteMagic::Connection.new(db)
|
39
67
|
end
|
40
68
|
|
41
|
-
|
69
|
+
# Returns whether the environment is production.
|
70
|
+
#
|
71
|
+
# @return [Boolean] whether the environment is production
|
42
72
|
def in_production?
|
43
73
|
!!ENV['MORPH_URL']
|
44
74
|
end
|
45
75
|
|
76
|
+
private
|
77
|
+
|
46
78
|
def is_admin?
|
47
|
-
ENV['USER_ROLES'].to_s.split(
|
79
|
+
ENV['USER_ROLES'].to_s.split(',').include?('admin')
|
48
80
|
end
|
49
81
|
|
50
82
|
def get_vars
|
@@ -66,18 +98,14 @@ class Turbotlib
|
|
66
98
|
|
67
99
|
def path_to(dir)
|
68
100
|
if in_production?
|
69
|
-
|
101
|
+
"/#{dir}"
|
70
102
|
else
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
103
|
+
begin
|
104
|
+
Dir.mkdir(dir)
|
105
|
+
rescue Errno::EEXIST
|
106
|
+
end
|
76
107
|
|
77
|
-
|
78
|
-
begin
|
79
|
-
Dir.mkdir(location)
|
80
|
-
rescue Errno::EEXIST
|
108
|
+
dir
|
81
109
|
end
|
82
110
|
end
|
83
111
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'faraday_middleware'
|
5
|
+
require 'active_support/cache'
|
6
|
+
rescue LoadError
|
7
|
+
# Production doesn't need caching.
|
8
|
+
end
|
9
|
+
|
10
|
+
class Turbotlib
|
11
|
+
class Client
|
12
|
+
def self.new(cache_dir, expires_in, level, logdev)
|
13
|
+
Faraday.new do |connection|
|
14
|
+
connection.request :url_encoded
|
15
|
+
connection.request :retry
|
16
|
+
connection.use Faraday::Response::Logger, Logger.new('faraday', level, logdev)
|
17
|
+
if defined?(FaradayMiddleware) && cache_dir
|
18
|
+
connection.response :caching do
|
19
|
+
ActiveSupport::Cache::FileStore.new(cache_dir, expires_in: expires_in)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
connection.adapter Faraday.default_adapter
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'net/ftp'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
require 'retriable'
|
6
|
+
|
7
|
+
class Turbotlib
|
8
|
+
class FTPDelegator < SimpleDelegator
|
9
|
+
# echanges.dila.gouv.fr sometimes returns a local IP (192.168.30.9) for the
|
10
|
+
# host in `#makepasv`. We can store the first host received (which we assume
|
11
|
+
# to be good), and return it every time. However, even with a good IP, the
|
12
|
+
# next command times out. So, we instead retry the entire command with a new
|
13
|
+
# client, after closing the old client.
|
14
|
+
def method_missing(m, *args, &block)
|
15
|
+
on_retry = Proc.new do |exception, try, elapsed_time, next_interval|
|
16
|
+
@delegate_sd_obj.error("#{exception.message} on #{@delegate_sd_obj.last_cmd}")
|
17
|
+
@delegate_sd_obj.close
|
18
|
+
|
19
|
+
ftp = FTP.new(*@delegate_sd_obj.initialize_args)
|
20
|
+
ftp.logger = @delegate_sd_obj.logger
|
21
|
+
ftp.root_path = @delegate_sd_obj.root_path
|
22
|
+
ftp.passive = true
|
23
|
+
|
24
|
+
ftp.login
|
25
|
+
dir = @delegate_sd_obj.last_dir.to_s
|
26
|
+
unless dir.empty?
|
27
|
+
ftp.chdir(dir)
|
28
|
+
end
|
29
|
+
|
30
|
+
__setobj__(ftp)
|
31
|
+
end
|
32
|
+
|
33
|
+
exception_classes = [Errno::ETIMEDOUT, EOFError]
|
34
|
+
if Net.const_defined?(:ReadTimeout) # Ruby 2
|
35
|
+
exception_classes << Net::ReadTimeout
|
36
|
+
end
|
37
|
+
|
38
|
+
Retriable.retriable(on: exception_classes, on_retry: on_retry) do
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class FTP < Net::FTP
|
45
|
+
extend Forwardable
|
46
|
+
|
47
|
+
attr_accessor :logger, :root_path
|
48
|
+
attr_reader :initialize_args, :last_dir, :last_cmd
|
49
|
+
|
50
|
+
def_delegators :@logger, :debug, :info, :warn, :error, :fatal
|
51
|
+
|
52
|
+
# Downloads a remote file.
|
53
|
+
#
|
54
|
+
# @param [String] remotefile the name of the remote file
|
55
|
+
# @return [File] a local file with the remote file's contents
|
56
|
+
def download(remotefile)
|
57
|
+
info("get #{remotefile}")
|
58
|
+
|
59
|
+
path = File.join(root_path, pwd, remotefile)
|
60
|
+
|
61
|
+
if Env.development? && File.exist?(path)
|
62
|
+
File.open(path)
|
63
|
+
else
|
64
|
+
FileUtils.mkdir_p(File.dirname(path))
|
65
|
+
File.open(path, 'w') do |f|
|
66
|
+
getbinaryfile(remotefile, f.path)
|
67
|
+
end
|
68
|
+
File.open(path)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize(host = nil, user = nil, passwd = nil, acct = nil)
|
73
|
+
# Store so we can recreate an FTP client.
|
74
|
+
@initialize_args = [host, user, passwd, acct]
|
75
|
+
@last_dir = Pathname.new('')
|
76
|
+
@last_cmd = nil
|
77
|
+
super
|
78
|
+
end
|
79
|
+
|
80
|
+
def login(*args)
|
81
|
+
info('login')
|
82
|
+
super
|
83
|
+
end
|
84
|
+
|
85
|
+
def nlst(dir = nil)
|
86
|
+
if dir
|
87
|
+
info("nlst #{dir}")
|
88
|
+
else
|
89
|
+
info('nlst')
|
90
|
+
end
|
91
|
+
super
|
92
|
+
end
|
93
|
+
|
94
|
+
def chdir(dirname)
|
95
|
+
info("chdir #{dirname}")
|
96
|
+
super
|
97
|
+
# Store so we can resume from the directory.
|
98
|
+
@last_dir += dirname
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def putline(line)
|
104
|
+
# Store so we can report the command that errored.
|
105
|
+
@last_cmd = line
|
106
|
+
super
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
class Turbotlib
|
4
|
+
class Logger
|
5
|
+
def self.new(progname, level, logdev)
|
6
|
+
logger = ::Logger.new(logdev)
|
7
|
+
logger.level = ::Logger.const_get(level)
|
8
|
+
logger.progname = progname
|
9
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
10
|
+
"#{datetime.strftime('%T')} #{severity} #{progname}: #{msg}\n"
|
11
|
+
end
|
12
|
+
logger
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Turbotlib
|
2
|
+
class Processor
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
attr_reader :client
|
6
|
+
|
7
|
+
def_delegators :@logger, :debug, :info, :warn, :error, :fatal
|
8
|
+
|
9
|
+
def initialize(output_dir, cache_dir, expires_in, level, logdev)
|
10
|
+
@logger = Logger.new('turbot', level, logdev)
|
11
|
+
@client = Client.new(cache_dir, expires_in, level, logdev)
|
12
|
+
|
13
|
+
@output_dir = output_dir
|
14
|
+
FileUtils.mkdir_p(@output_dir)
|
15
|
+
end
|
16
|
+
|
17
|
+
def get(url)
|
18
|
+
client.get(url).body
|
19
|
+
end
|
20
|
+
|
21
|
+
def assert(message)
|
22
|
+
error(message) unless yield
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [String] the present UTC time in ISO 8601 format
|
26
|
+
def now
|
27
|
+
Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/turbotlib/version.rb
CHANGED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require "simplecov"
|
4
|
+
require "coveralls"
|
5
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
6
|
+
SimpleCov.start do
|
7
|
+
add_filter "spec"
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rspec'
|
11
|
+
require 'webmock/rspec'
|
12
|
+
|
13
|
+
include WebMock::API
|
14
|
+
|
15
|
+
require 'webrick'
|
16
|
+
require File.dirname(__FILE__) + '/../lib/turbotlib'
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Turbotlib::FTPDelegator do
|
4
|
+
T = '\d\d:\d\d:\d\d'
|
5
|
+
|
6
|
+
let :logdev do
|
7
|
+
StringIO.new
|
8
|
+
end
|
9
|
+
|
10
|
+
let :logger do
|
11
|
+
Turbotlib::Logger.new('turbot', 'INFO', logdev)
|
12
|
+
end
|
13
|
+
|
14
|
+
let :ftp do
|
15
|
+
Turbotlib::FTP.new('echanges.dila.gouv.fr')
|
16
|
+
end
|
17
|
+
|
18
|
+
let :delegator do
|
19
|
+
Turbotlib::FTPDelegator.new(ftp)
|
20
|
+
end
|
21
|
+
|
22
|
+
before do
|
23
|
+
# Stub the methods that call `Net::FTP#open_socket`.
|
24
|
+
allow_any_instance_of(Net::FTP).to receive(:connect)
|
25
|
+
allow_any_instance_of(Net::FTP).to receive(:transfercmd).and_return(double({
|
26
|
+
:close => nil,
|
27
|
+
:gets => nil,
|
28
|
+
:read => nil,
|
29
|
+
:read_timeout= => nil,
|
30
|
+
:shutdown => nil,
|
31
|
+
}))
|
32
|
+
# Stub the default socket.
|
33
|
+
allow_any_instance_of(Net::FTP::NullSocket).to receive(:write)
|
34
|
+
allow_any_instance_of(Net::FTP::NullSocket).to receive(:closed?).and_return(true)
|
35
|
+
allow_any_instance_of(Net::FTP::NullSocket).to receive(:readline).and_return('200')
|
36
|
+
end
|
37
|
+
|
38
|
+
before(:each) do
|
39
|
+
delegator.logger = logger
|
40
|
+
delegator.login
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#initialize' do
|
44
|
+
it 'succeeds' do
|
45
|
+
expect(logdev.string).to match(/\A#{T} INFO turbot: login\n\z/)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#nlst' do
|
50
|
+
it 'logs the command' do
|
51
|
+
delegator.nlst
|
52
|
+
expect(logdev.string).to match(/\A#{T} INFO turbot: login\n#{T} INFO turbot: nlst\n\z/)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'logs the command and the directory' do
|
56
|
+
delegator.nlst('foo')
|
57
|
+
expect(logdev.string).to match(/\A#{T} INFO turbot: login\n#{T} INFO turbot: nlst foo\n\z/)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#chdir' do
|
62
|
+
it 'succeeds' do
|
63
|
+
delegator.chdir('BODACC')
|
64
|
+
expect(logdev.string).to match(/\A#{T} INFO turbot: login\n#{T} INFO turbot: chdir BODACC\n\z/)
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'on error' do
|
68
|
+
before do
|
69
|
+
expect(ftp).to receive(:putline).once.and_raise(Errno::ETIMEDOUT)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'retries' do
|
73
|
+
delegator.chdir('BODACC')
|
74
|
+
expect(logdev.string).to match(/\A#{T} INFO turbot: login\n#{T} INFO turbot: chdir BODACC\n#{T} ERROR turbot: (?:Connection|Operation) timed out on TYPE I\n#{T} INFO turbot: login\n#{T} INFO turbot: chdir BODACC\n\z/)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Turbotlib::Logger do
|
4
|
+
let :logdev do
|
5
|
+
StringIO.new
|
6
|
+
end
|
7
|
+
|
8
|
+
let :logger do
|
9
|
+
Turbotlib::Logger.new('foo', 'INFO', logdev)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#info' do
|
13
|
+
it 'logs formatted messages' do
|
14
|
+
logger.info('bar')
|
15
|
+
expect(logdev.string).to match(/\A\d\d:\d\d:\d\d INFO foo: bar\n\z/)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Turbotlib::Processor do
|
4
|
+
after do
|
5
|
+
if Dir.exist?('output')
|
6
|
+
Dir.rmdir('output')
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let :logdev do
|
11
|
+
StringIO.new
|
12
|
+
end
|
13
|
+
|
14
|
+
let :processor do
|
15
|
+
Turbotlib::Processor.new('output', '_cache', 60, 'INFO', logdev)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#initialize' do
|
19
|
+
it 'creates an output directory' do
|
20
|
+
processor
|
21
|
+
expect(Dir.exist?('output')).to eq(true)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#get' do
|
26
|
+
it 'returns the body of an HTTP response' do
|
27
|
+
stub_request(:get, 'http://example.com/').to_return(:status => 200, :body => 'test')
|
28
|
+
|
29
|
+
expect(processor.get('http://example.com/')).to eq('test')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#assert' do
|
34
|
+
it 'logs no message if the block returns true' do
|
35
|
+
processor.assert('passes'){true}
|
36
|
+
expect(logdev.string).to eq('')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'logs a message if the block returns false' do
|
40
|
+
processor.assert('fails'){false}
|
41
|
+
expect(logdev.string).to match(/\A\d\d:\d\d:\d\d ERROR turbot: fails\n\z/)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#now' do
|
46
|
+
it 'returns the current time in ISO 8601' do
|
47
|
+
expect(processor.now).to match(/\A\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ\z/)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/turbotlib_spec.rb
CHANGED
@@ -1,83 +1,83 @@
|
|
1
|
-
require '
|
2
|
-
require 'fileutils'
|
1
|
+
require 'spec_helper'
|
3
2
|
|
4
3
|
describe Turbotlib do
|
5
|
-
describe
|
6
|
-
it
|
4
|
+
describe '.log' do
|
5
|
+
it 'prints a message' do
|
7
6
|
expect {
|
8
|
-
Turbotlib.log(
|
7
|
+
Turbotlib.log('hi')
|
9
8
|
}.to output("hi\n").to_stderr
|
10
9
|
end
|
11
10
|
end
|
12
11
|
|
13
|
-
describe
|
14
|
-
context
|
12
|
+
describe '.data_dir' do
|
13
|
+
context 'when developing' do
|
15
14
|
after do
|
16
|
-
|
15
|
+
Dir.rmdir('data')
|
17
16
|
end
|
18
17
|
|
19
|
-
it "
|
20
|
-
expect(Turbotlib.data_dir).to eq(
|
21
|
-
|
22
|
-
|
23
|
-
it "should create data directory" do
|
24
|
-
Turbotlib.data_dir
|
25
|
-
expect(File.exists?("data")).to eq(true)
|
18
|
+
it 'returns "data" and creates the directory' do
|
19
|
+
expect(Turbotlib.data_dir).to eq('data')
|
20
|
+
expect(Dir.exists?('data')).to eq(true)
|
26
21
|
end
|
27
22
|
end
|
28
23
|
|
29
|
-
context
|
24
|
+
context 'when running in morph' do
|
30
25
|
before do
|
31
|
-
allow(ENV).to receive(:[]).with(
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should return /data" do
|
35
|
-
expect(Turbotlib.data_dir).to eq("/data")
|
26
|
+
allow(ENV).to receive(:[]).with('MORPH_URL').and_return('something')
|
36
27
|
end
|
37
28
|
|
38
|
-
it "
|
39
|
-
expect(
|
29
|
+
it 'returns "/data" and does not create the directory' do
|
30
|
+
expect(Turbotlib.data_dir).to eq('/data')
|
31
|
+
expect(Dir.exists?('data')).to eq(false)
|
40
32
|
end
|
41
33
|
end
|
42
34
|
end
|
43
35
|
|
44
|
-
describe
|
45
|
-
context
|
36
|
+
describe '.sources_dir' do
|
37
|
+
context 'when developing' do
|
46
38
|
after do
|
47
|
-
|
39
|
+
Dir.rmdir('sources')
|
48
40
|
end
|
49
41
|
|
50
|
-
it "
|
51
|
-
expect(Turbotlib.sources_dir).to eq(
|
52
|
-
|
53
|
-
|
54
|
-
it "should create sources directory" do
|
55
|
-
Turbotlib.sources_dir
|
56
|
-
expect(File.exists?("sources")).to eq(true)
|
42
|
+
it 'returns "sources" and creates the directory' do
|
43
|
+
expect(Turbotlib.sources_dir).to eq('sources')
|
44
|
+
expect(Dir.exists?('sources')).to eq(true)
|
57
45
|
end
|
58
46
|
end
|
59
47
|
|
60
|
-
context
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
48
|
+
context 'when running in morph' do
|
49
|
+
before do
|
50
|
+
allow(Turbotlib).to receive(:in_production?).and_return(true)
|
51
|
+
end
|
65
52
|
|
66
|
-
|
67
|
-
|
53
|
+
context 'and not an admin' do
|
54
|
+
it 'raises an error' do
|
55
|
+
expect{Turbotlib.sources_dir}.to raise_error("Only admins are permitted to write to `sources_dir`")
|
68
56
|
end
|
69
57
|
end
|
70
58
|
|
71
|
-
context
|
59
|
+
context 'and an admin' do
|
72
60
|
before do
|
73
|
-
allow(Turbotlib).to receive(:in_production?).and_return(true)
|
74
61
|
allow(Turbotlib).to receive(:is_admin?).and_return(true)
|
75
62
|
end
|
76
63
|
|
77
|
-
it "
|
78
|
-
expect(Turbotlib.sources_dir).to eq(
|
64
|
+
it 'returns "/sources" and does not create the directory' do
|
65
|
+
expect(Turbotlib.sources_dir).to eq('/sources')
|
66
|
+
expect(Dir.exists?('/sources')).to eq(false)
|
79
67
|
end
|
80
68
|
end
|
81
69
|
end
|
82
70
|
end
|
71
|
+
|
72
|
+
describe '.save_var' do
|
73
|
+
after do
|
74
|
+
FileUtils.rm_rf('data')
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'saves and returns the variable' do
|
78
|
+
expect(Turbotlib.get_var('foo')).to eq(nil)
|
79
|
+
expect(Turbotlib.save_var('foo', 'bar')).to eq('bar')
|
80
|
+
expect(Turbotlib.get_var('foo')).to eq('bar')
|
81
|
+
end
|
82
|
+
end
|
83
83
|
end
|
data/turbotlib.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path('../lib/turbotlib/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = "turbotlib"
|
5
|
+
gem.version = TurbotLib::VERSION
|
6
|
+
|
7
|
+
gem.author = "OpenCorporates"
|
8
|
+
gem.email = "bots@opencorporates.com"
|
9
|
+
gem.homepage = "https://github.com/openc/turbotlib-ruby"
|
10
|
+
gem.summary = "Helpers for writing Turbot bots"
|
11
|
+
gem.license = "MIT"
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split("\n")
|
14
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
|
18
|
+
gem.required_ruby_version = '>=1.9.2'
|
19
|
+
|
20
|
+
gem.add_runtime_dependency "scraperwiki", "~> 3.0.2"
|
21
|
+
gem.add_runtime_dependency "faraday", "~> 0.9.0"
|
22
|
+
gem.add_runtime_dependency "retriable", "~> 2.0.2"
|
23
|
+
|
24
|
+
gem.add_development_dependency "activesupport", "~> 4.1.0"
|
25
|
+
gem.add_development_dependency "coveralls"
|
26
|
+
gem.add_development_dependency "faraday_middleware"
|
27
|
+
gem.add_development_dependency "rake"
|
28
|
+
gem.add_development_dependency "rspec", "~> 3.4"
|
29
|
+
gem.add_development_dependency "webmock"
|
30
|
+
end
|
metadata
CHANGED
@@ -1,65 +1,193 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: turbotlib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.10
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
|
-
-
|
7
|
+
- OpenCorporates
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2016-02-13 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: scraperwiki
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 3.0.2
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 3.0.2
|
30
|
-
|
31
|
-
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.9.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: retriable
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.0.2
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.0.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 4.1.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 4.1.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: coveralls
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: faraday_middleware
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '3.4'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3.4'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: webmock
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description:
|
140
|
+
email: bots@opencorporates.com
|
32
141
|
executables: []
|
33
142
|
extensions: []
|
34
143
|
extra_rdoc_files: []
|
35
144
|
files:
|
145
|
+
- ".gitignore"
|
146
|
+
- ".rspec"
|
147
|
+
- ".travis.yml"
|
148
|
+
- Gemfile
|
149
|
+
- README.md
|
150
|
+
- Rakefile
|
36
151
|
- lib/turbotlib.rb
|
152
|
+
- lib/turbotlib/client.rb
|
153
|
+
- lib/turbotlib/ftp.rb
|
154
|
+
- lib/turbotlib/logger.rb
|
155
|
+
- lib/turbotlib/processor.rb
|
37
156
|
- lib/turbotlib/version.rb
|
157
|
+
- spec/spec_helper.rb
|
158
|
+
- spec/turbotlib/ftp_spec.rb
|
159
|
+
- spec/turbotlib/logger_spec.rb
|
160
|
+
- spec/turbotlib/processor_spec.rb
|
38
161
|
- spec/turbotlib_spec.rb
|
39
|
-
|
162
|
+
- turbotlib.gemspec
|
163
|
+
homepage: https://github.com/openc/turbotlib-ruby
|
40
164
|
licenses:
|
41
165
|
- MIT
|
166
|
+
metadata: {}
|
42
167
|
post_install_message:
|
43
168
|
rdoc_options: []
|
44
169
|
require_paths:
|
45
170
|
- lib
|
46
171
|
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
-
none: false
|
48
172
|
requirements:
|
49
|
-
- -
|
173
|
+
- - ">="
|
50
174
|
- !ruby/object:Gem::Version
|
51
175
|
version: 1.9.2
|
52
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
-
none: false
|
54
177
|
requirements:
|
55
|
-
- -
|
178
|
+
- - ">="
|
56
179
|
- !ruby/object:Gem::Version
|
57
180
|
version: '0'
|
58
181
|
requirements: []
|
59
182
|
rubyforge_project:
|
60
|
-
rubygems_version:
|
183
|
+
rubygems_version: 2.4.5
|
61
184
|
signing_key:
|
62
|
-
specification_version:
|
63
|
-
summary: Helpers for writing
|
64
|
-
test_files:
|
185
|
+
specification_version: 4
|
186
|
+
summary: Helpers for writing Turbot bots
|
187
|
+
test_files:
|
188
|
+
- spec/spec_helper.rb
|
189
|
+
- spec/turbotlib/ftp_spec.rb
|
190
|
+
- spec/turbotlib/logger_spec.rb
|
191
|
+
- spec/turbotlib/processor_spec.rb
|
192
|
+
- spec/turbotlib_spec.rb
|
65
193
|
has_rdoc:
|