lyber-core 4.1.3 → 4.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/lyber_core.rb +3 -0
- data/lib/lyber_core/base.rb +91 -0
- data/lib/lyber_core/log.rb +24 -35
- data/lib/lyber_core/return_state.rb +9 -11
- data/lib/lyber_core/robot.rb +21 -31
- data/lib/tasks/rdoc.rake +11 -12
- metadata +37 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1489790b66195312397f9325c4e61119086d903
|
4
|
+
data.tar.gz: e5db26df5720035e46f22360246f680dfbe87b10
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5af41b19bb03d42890596fe374187cbc856d768fedff25b104522b2717a08adc2dff41d5c826455284cd89a7d761906ecb57633c8a0d2419ebd9616f7ab9ce2f
|
7
|
+
data.tar.gz: 0647f4d26c22e049c59bbc814f1dafc5463169e2e0ee687a77d9b0e4051d37ac9015280f7e2bc0fa967a6b47e2a315adaf4fd418adcdc6b712562ff7149fba09
|
data/lib/lyber_core.rb
CHANGED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'active_support'
|
3
|
+
|
4
|
+
module LyberCore
|
5
|
+
# The skeleton of robots, a replacement for LyberCore::Robot
|
6
|
+
# @example To migrate from LyberCore::Robot, replace
|
7
|
+
# class MyRobot
|
8
|
+
# include LyberCore::Robot
|
9
|
+
# def initialize
|
10
|
+
# new(REPOSITORY, WORKFLOW_NAME, ROBOT_NAME)
|
11
|
+
# end
|
12
|
+
# def perform ...
|
13
|
+
# end
|
14
|
+
# @example Usage: implement self.worker and override #perform, as before
|
15
|
+
# class MyRobot < LyberCore::Base
|
16
|
+
# def self.worker
|
17
|
+
# new('sdr', 'preservationIngestWF', 'ingest-poison')
|
18
|
+
# end
|
19
|
+
# def perform ...
|
20
|
+
# end
|
21
|
+
class Base
|
22
|
+
# Called by job-manager: instantiate the Robot and call #work with the druid
|
23
|
+
# @param [String] druid
|
24
|
+
# @note Override the instance method #perform, probably not this one
|
25
|
+
def self.perform(druid)
|
26
|
+
worker.work(druid)
|
27
|
+
end
|
28
|
+
|
29
|
+
# get an instance, without knowing the params for .new()
|
30
|
+
# @return [LyberCore::Base]
|
31
|
+
def self.worker
|
32
|
+
raise NotImplementedError, 'Implement class method self.worker on the subclass'
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_accessor :repo, :workflow_name, :step_name, :check_queued_status, :workflow_service
|
36
|
+
|
37
|
+
def initialize(repo, workflow_name, step_name, opts = {})
|
38
|
+
Signal.trap('QUIT') { puts "#{Process.pid} ignoring SIGQUIT" } # SIGQUIT ignored to let the robot finish
|
39
|
+
@repo = repo
|
40
|
+
@workflow_name = workflow_name
|
41
|
+
@step_name = step_name
|
42
|
+
@check_queued_status = opts.fetch(:check_queued_status, true)
|
43
|
+
@workflow_service = opts.fetch(:workflow_service, Dor::WorkflowService)
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Logger]
|
47
|
+
def logger
|
48
|
+
unless @log_init # one time
|
49
|
+
LyberCore::Log.set_logfile($stdout) # let process manager(bluepill) handle logging
|
50
|
+
@log_init = true
|
51
|
+
end
|
52
|
+
LyberCore::Log
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sets up logging, timing and error handling of the job
|
56
|
+
# Calls the #perform method, then sets workflow to 'completed' or 'error' depending on success
|
57
|
+
def work(druid)
|
58
|
+
logger.info "#{druid} processing"
|
59
|
+
return if check_queued_status && !item_queued?(druid)
|
60
|
+
result = nil
|
61
|
+
elapsed = Benchmark.realtime { result = perform(druid) }
|
62
|
+
if result.is_a?(LyberCore::Robot::ReturnState)
|
63
|
+
workflow_state = result.status
|
64
|
+
note = result.note unless result.note.blank?
|
65
|
+
else
|
66
|
+
workflow_state = 'completed' # default
|
67
|
+
end
|
68
|
+
note ||= Socket.gethostname # default
|
69
|
+
workflow_service.update_workflow_status(repo, druid, workflow_name, step_name, workflow_state, elapsed: elapsed, note: note)
|
70
|
+
logger.info "Finished #{druid} in #{format('%0.4f', elapsed)}s"
|
71
|
+
rescue StandardError => e
|
72
|
+
Honeybadger.notify(e) if defined? Honeybadger
|
73
|
+
begin
|
74
|
+
logger.error e.message + "\n" + e.backtrace.join("\n")
|
75
|
+
workflow_service.update_workflow_error_status(repo, druid, workflow_name, step_name, e.message, error_text: Socket.gethostname)
|
76
|
+
rescue StandardError => e2
|
77
|
+
logger.error "Cannot set #{druid} to status='error'\n" + e2.message + "\n" + e2.backtrace.join("\n")
|
78
|
+
raise e2 # send exception to Resque failed queue
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def item_queued?(druid)
|
85
|
+
status = workflow_service.get_workflow_status(repo, druid, workflow_name, step_name)
|
86
|
+
return true if status =~ /queued/i
|
87
|
+
logger.warn "Item is not queued, but has status of '#{status}'. Will skip processing"
|
88
|
+
false
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/lyber_core/log.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
|
-
|
2
1
|
module LyberCore
|
3
|
-
|
4
2
|
class LyberCore::Log
|
5
3
|
require 'logger'
|
6
4
|
|
7
5
|
# Default values
|
8
|
-
DEFAULT_LOGFILE =
|
6
|
+
DEFAULT_LOGFILE = '/tmp/lybercore_log.log'.freeze # TODO change to STDOUT?
|
9
7
|
DEFAULT_LOG_LEVEL = Logger::INFO
|
10
|
-
DEFAULT_FORMATTER = proc
|
11
|
-
|
8
|
+
DEFAULT_FORMATTER = proc do |s, t, p, m|
|
9
|
+
"%5s [%s] (%s) %s :: %s\n" % [s, t.strftime('%Y-%m-%d %H:%M:%S'), $$, p, m]
|
10
|
+
end
|
12
11
|
|
13
12
|
# Initial state
|
14
13
|
@@logfile = DEFAULT_LOGFILE
|
@@ -27,27 +26,22 @@ module LyberCore
|
|
27
26
|
|
28
27
|
# The current location of the logfile
|
29
28
|
def Log.logfile
|
30
|
-
|
29
|
+
@@logfile
|
31
30
|
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
32
|
# Accepts a filename as an argument, and checks to see whether that file can be
|
36
33
|
# opened for writing. If it can be opened, it closes the existing Logger object
|
37
34
|
# and re-opens it with the new logfile location. It raises an exception if it
|
38
35
|
# cannot write to the specified logfile.
|
39
36
|
def Log.set_logfile(new_logfile)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
raise e, "Couldn't initialize logfile #{new_logfile} because\n#{e.message}: #{e.backtrace.join(%{\n})}}"
|
49
|
-
end
|
50
|
-
|
37
|
+
current_log_level = @@log.level
|
38
|
+
current_formatter = @@log.formatter
|
39
|
+
@@log = Logger.new(new_logfile)
|
40
|
+
@@logfile = new_logfile
|
41
|
+
@@log.level = current_log_level
|
42
|
+
@@log.formatter = current_formatter
|
43
|
+
rescue Exception => e
|
44
|
+
raise e, "Couldn't initialize logfile #{new_logfile} because\n#{e.message}: #{e.backtrace.join(%(\n))}}"
|
51
45
|
end
|
52
46
|
|
53
47
|
# Set the log level.
|
@@ -59,18 +53,16 @@ module LyberCore
|
|
59
53
|
# Logger::INFO (1): generic (useful) information about system operation
|
60
54
|
# Logger::DEBUG (0): low-level information for developers
|
61
55
|
def Log.set_level(loglevel)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@@log.level = 0
|
70
|
-
end
|
71
|
-
rescue Exception => e
|
72
|
-
raise e, "Couldn't set log level because\n#{e.message}: #{e.backtrace.join(%{\n})}"
|
56
|
+
if [0, 1, 2, 3, 4].include? loglevel
|
57
|
+
@@log.level = loglevel
|
58
|
+
@@log.debug "Setting LyberCore::Log.level to #{loglevel}"
|
59
|
+
else
|
60
|
+
@@log.warn "I received an invalid option for log level. I expected a number between 0 and 4 but I got #{loglevel}"
|
61
|
+
@@log.warn "I'm setting the loglevel to 0 (debug) because you seem to be having trouble."
|
62
|
+
@@log.level = 0
|
73
63
|
end
|
64
|
+
rescue Exception => e
|
65
|
+
raise e, "Couldn't set log level because\n#{e.message}: #{e.backtrace.join(%(\n))}"
|
74
66
|
end
|
75
67
|
|
76
68
|
# Return the current log level
|
@@ -105,10 +97,7 @@ module LyberCore
|
|
105
97
|
|
106
98
|
def Log.exception_message(e)
|
107
99
|
msg = e.inspect.split($/).join('; ') + "\n"
|
108
|
-
msg << e.backtrace.join("\n") if
|
100
|
+
msg << e.backtrace.join("\n") if e.backtrace
|
109
101
|
end
|
110
|
-
|
111
102
|
end
|
112
|
-
|
113
|
-
|
114
|
-
end
|
103
|
+
end
|
@@ -1,38 +1,36 @@
|
|
1
1
|
# this object defines the allowed states robots can optionally return upon completion
|
2
|
-
# if the return value of the "perform" step is an object of this type and the status value is set an allowed value,
|
2
|
+
# if the return value of the "perform" step is an object of this type and the status value is set an allowed value,
|
3
3
|
# it will be used to set the final workflow state for that druid
|
4
4
|
module LyberCore
|
5
5
|
module Robot
|
6
6
|
class ReturnState
|
7
|
-
|
8
7
|
attr_reader :status
|
9
8
|
attr_accessor :note
|
10
|
-
ALLOWED_RETURN_STATES = %w
|
11
|
-
DEFAULT_RETURN_STATE = 'completed'
|
12
|
-
|
9
|
+
ALLOWED_RETURN_STATES = %w[completed skipped waiting].freeze
|
10
|
+
DEFAULT_RETURN_STATE = 'completed'.freeze
|
11
|
+
|
13
12
|
def self.SKIPPED
|
14
|
-
|
13
|
+
new(status: 'skipped')
|
15
14
|
end
|
16
15
|
|
17
16
|
def self.COMPLETED
|
18
|
-
|
17
|
+
new(status: 'completed')
|
19
18
|
end
|
20
19
|
|
21
20
|
def self.WAITING
|
22
|
-
|
21
|
+
new(status: 'waiting')
|
23
22
|
end
|
24
23
|
|
25
24
|
def initialize(params = {})
|
26
25
|
self.status = params[:status] || DEFAULT_RETURN_STATE
|
27
|
-
self.note = params[:note] ||
|
26
|
+
self.note = params[:note] || ''
|
28
27
|
end
|
29
|
-
|
28
|
+
|
30
29
|
def status=(value)
|
31
30
|
state = value.to_s.downcase
|
32
31
|
raise 'invalid return state' unless ALLOWED_RETURN_STATES.include? state
|
33
32
|
@status = state
|
34
33
|
end
|
35
|
-
|
36
34
|
end
|
37
35
|
end
|
38
36
|
end
|
data/lib/lyber_core/robot.rb
CHANGED
@@ -5,25 +5,20 @@ require 'active_support/core_ext/string/inflections' # camelcase
|
|
5
5
|
|
6
6
|
module LyberCore
|
7
7
|
module Robot
|
8
|
-
|
9
8
|
# Add the ClassMethods to the class this is being mixed into
|
10
|
-
def self.included
|
9
|
+
def self.included(base)
|
11
10
|
base.extend ClassMethods
|
12
11
|
end
|
13
12
|
|
14
13
|
module ClassMethods
|
15
|
-
|
16
14
|
# Called by job-manager on derived-class
|
17
15
|
# Instantiate the Robot and call #work with the passed in druid
|
18
16
|
def perform(druid)
|
19
|
-
|
20
|
-
klazz = self.name.split('::').inject(Object) {|o,c| o.const_get c}
|
21
|
-
bot = klazz.new
|
17
|
+
bot = new
|
22
18
|
bot.work druid
|
23
19
|
end
|
24
20
|
end
|
25
21
|
|
26
|
-
|
27
22
|
# Converts a given step to the Robot class name
|
28
23
|
# Examples:
|
29
24
|
#
|
@@ -35,15 +30,15 @@ module LyberCore
|
|
35
30
|
# @param [Hash] opts
|
36
31
|
# @option :repo_suffix defaults to `Repo`
|
37
32
|
# @return [String] The class name for the robot, e.g., `Robots::DorRepo::Accession:DescriptiveMetadata`
|
38
|
-
def self.step_to_classname
|
33
|
+
def self.step_to_classname(step, opts = {})
|
39
34
|
# generate the robot job class name
|
40
35
|
opts[:repo_suffix] ||= 'Repo'
|
41
36
|
r, w, s = step.split(/:/, 3)
|
42
|
-
|
37
|
+
[
|
43
38
|
'Robots',
|
44
39
|
r.camelcase + opts[:repo_suffix], # 'Dor' conflicts with dor-services
|
45
40
|
w.sub('WF', '').camelcase,
|
46
|
-
s.
|
41
|
+
s.tr('-', '_').camelcase
|
47
42
|
].join('::')
|
48
43
|
end
|
49
44
|
|
@@ -51,7 +46,7 @@ module LyberCore
|
|
51
46
|
attr_reader :workflow_service
|
52
47
|
|
53
48
|
def initialize(repo, workflow_name, step_name, opts = {})
|
54
|
-
Signal.trap(
|
49
|
+
Signal.trap('QUIT') { puts "#{Process.pid} ignoring SIGQUIT" } # SIGQUIT ignored to let the robot finish
|
55
50
|
@repo = repo
|
56
51
|
@workflow_name = workflow_name
|
57
52
|
@step_name = step_name
|
@@ -62,54 +57,49 @@ module LyberCore
|
|
62
57
|
# Sets up logging, timing and error handling of the job
|
63
58
|
# Calls the #perform method, then sets workflow to 'completed' or 'error' depending on success
|
64
59
|
def work(druid)
|
65
|
-
LyberCore::Log.set_logfile($stdout)
|
60
|
+
LyberCore::Log.set_logfile($stdout) # let process manager(bluepill) handle logging
|
66
61
|
LyberCore::Log.info "#{druid} processing"
|
67
62
|
return if @check_queued_status && !item_queued?(druid)
|
68
63
|
|
69
64
|
result = nil
|
70
65
|
elapsed = Benchmark.realtime do
|
71
|
-
result =
|
66
|
+
result = perform druid # implemented in the mixed-in robot class
|
72
67
|
end
|
73
68
|
|
74
69
|
# this is the default note to pass back to workflow service, but it can be overriden by a robot that uses the Lybercore::Robot::ReturnState object to return a status
|
75
70
|
note = Socket.gethostname
|
76
|
-
|
77
|
-
# the final workflow state is determined by the return value of the perform step, if it is a ReturnState object,
|
71
|
+
|
72
|
+
# the final workflow state is determined by the return value of the perform step, if it is a ReturnState object,
|
78
73
|
# we will use the defined status, otherwise default to completed
|
79
74
|
# if a note is passed back, we will also use that instead of the default
|
80
75
|
if result.class == LyberCore::Robot::ReturnState
|
81
76
|
workflow_state = result.status
|
82
77
|
note = result.note unless result.note.blank?
|
83
78
|
else
|
84
|
-
workflow_state = 'completed'
|
79
|
+
workflow_state = 'completed'
|
85
80
|
end
|
86
|
-
|
87
|
-
# update the workflow status from its current state to the state returned by perform (or 'completed' as the default)
|
88
|
-
workflow_service.update_workflow_status @repo, druid, @workflow_name, @step_name, workflow_state, :elapsed => elapsed, :note => note
|
89
|
-
LyberCore::Log.info "Finished #{druid} in #{sprintf("%0.4f",elapsed)}s"
|
90
81
|
|
91
|
-
|
82
|
+
# update the workflow status from its current state to the state returned by perform (or 'completed' as the default)
|
83
|
+
workflow_service.update_workflow_status(@repo, druid, @workflow_name, @step_name, workflow_state, elapsed: elapsed, note: note)
|
84
|
+
LyberCore::Log.info "Finished #{druid} in #{sprintf('%0.4f', elapsed)}s"
|
85
|
+
rescue StandardError => e
|
92
86
|
Honeybadger.notify(e) if defined? Honeybadger
|
93
87
|
begin
|
94
88
|
LyberCore::Log.error e.message + "\n" + e.backtrace.join("\n")
|
95
|
-
workflow_service.update_workflow_error_status
|
96
|
-
rescue => e2
|
89
|
+
workflow_service.update_workflow_error_status(@repo, druid, @workflow_name, @step_name, e.message, error_text: Socket.gethostname)
|
90
|
+
rescue StandardError => e2
|
97
91
|
LyberCore::Log.error "Cannot set #{druid} to status='error'\n" + e2.message + "\n" + e2.backtrace.join("\n")
|
98
92
|
raise e2 # send exception to Resque failed queue
|
99
93
|
end
|
100
94
|
end
|
101
95
|
|
102
|
-
|
96
|
+
private
|
103
97
|
|
104
98
|
def item_queued?(druid)
|
105
99
|
status = workflow_service.get_workflow_status(@repo, druid, @workflow_name, @step_name)
|
106
|
-
if
|
107
|
-
|
108
|
-
|
109
|
-
LyberCore::Log.warn "Item is not queued, but has status of '#{status}'. Will skip processing"
|
110
|
-
return false
|
111
|
-
end
|
100
|
+
return true if status =~ /queued/i
|
101
|
+
LyberCore::Log.warn "Item is not queued, but has status of '#{status}'. Will skip processing"
|
102
|
+
false
|
112
103
|
end
|
113
|
-
|
114
104
|
end
|
115
105
|
end
|
data/lib/tasks/rdoc.rake
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
desc
|
2
|
-
task :
|
1
|
+
desc 'Generate RDoc'
|
2
|
+
task doc: ['doc:generate']
|
3
3
|
|
4
4
|
namespace :doc do
|
5
5
|
project_root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
@@ -10,23 +10,22 @@ namespace :doc do
|
|
10
10
|
require 'yard/rake/yardoc_task'
|
11
11
|
|
12
12
|
YARD::Rake::YardocTask.new(:generate) do |yt|
|
13
|
-
yt.files = Dir.glob(File.join(project_root, 'lib', '*.rb')) +
|
13
|
+
yt.files = Dir.glob(File.join(project_root, 'lib', '*.rb')) +
|
14
14
|
Dir.glob(File.join(project_root, 'lib', '**', '*.rb')) +
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
[File.join(project_root, 'README.rdoc')] +
|
16
|
+
[File.join(project_root, 'LICENSE')]
|
17
|
+
|
18
18
|
yt.options = ['--output-dir', doc_destination, '--readme', 'README.rdoc']
|
19
19
|
end
|
20
20
|
rescue LoadError
|
21
|
-
desc
|
21
|
+
desc 'Generate YARD Documentation'
|
22
22
|
task :generate do
|
23
|
-
abort
|
23
|
+
abort 'Please install the YARD gem to generate rdoc.'
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
desc
|
27
|
+
desc 'Remove generated documenation'
|
28
28
|
task :clean do
|
29
|
-
rm_r doc_destination if File.
|
29
|
+
rm_r doc_destination if File.exist?(doc_destination)
|
30
30
|
end
|
31
|
-
|
32
|
-
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lyber-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.
|
4
|
+
version: 4.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alpana Pande
|
@@ -16,8 +16,22 @@ authors:
|
|
16
16
|
autorequire:
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
|
-
date:
|
19
|
+
date: 2018-04-16 00:00:00.000000000 Z
|
20
20
|
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: activesupport
|
23
|
+
requirement: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
type: :runtime
|
29
|
+
prerelease: false
|
30
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
21
35
|
- !ruby/object:Gem::Dependency
|
22
36
|
name: dor-workflow-service
|
23
37
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,13 +53,13 @@ dependencies:
|
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '3'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: coveralls
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - ">="
|
46
60
|
- !ruby/object:Gem::Version
|
47
61
|
version: '0'
|
48
|
-
type: :
|
62
|
+
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
@@ -95,7 +109,7 @@ dependencies:
|
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '3.0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
112
|
+
name: rubocop
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - ">="
|
@@ -109,7 +123,21 @@ dependencies:
|
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
126
|
+
name: rubocop-rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.24'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.24'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: yard
|
113
141
|
requirement: !ruby/object:Gem::Requirement
|
114
142
|
requirements:
|
115
143
|
- - ">="
|
@@ -134,6 +162,7 @@ files:
|
|
134
162
|
- LICENSE
|
135
163
|
- README.md
|
136
164
|
- lib/lyber_core.rb
|
165
|
+
- lib/lyber_core/base.rb
|
137
166
|
- lib/lyber_core/log.rb
|
138
167
|
- lib/lyber_core/return_state.rb
|
139
168
|
- lib/lyber_core/robot.rb
|
@@ -158,8 +187,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
187
|
version: 1.3.6
|
159
188
|
requirements: []
|
160
189
|
rubyforge_project:
|
161
|
-
rubygems_version: 2.6.
|
190
|
+
rubygems_version: 2.6.11
|
162
191
|
signing_key:
|
163
192
|
specification_version: 4
|
164
193
|
summary: Core services used by the SUL Digital Library
|
165
194
|
test_files: []
|
195
|
+
has_rdoc:
|