lib/yuuki/caller.rb in yuuki-0.1.7 vs lib/yuuki/caller.rb in yuuki-0.1.8
- old
+ new
@@ -1,41 +1,49 @@
# frozen_string_literal: true
require 'set'
require 'yuuki/runner'
+require 'yoshinon'
module Yuuki
class Caller
# requires all the rb files in the given directory
# @param [String] require_dir directory
# @param [Boolean] recursive
def self.require_dir(require_dir, recursive: false)
- Dir.glob(recursive ? "#{require_dir}/**/*.rb" : "#{require_dir}/*.rb"){|file| require file}
+ Dir.glob(recursive ? "#{require_dir}/**/*.rb" : "#{require_dir}/*.rb").sort.each {|file| require file}
end
# @param [Object] instances
- def initialize(*instances)
+ def initialize(*instances, use_yoshinon: true)
@instances = Set.new
@threads = []
add(*instances)
+ @use_yoshinon = use_yoshinon
end
# adds instances to yuuki
# @param [Object] instances
def add(*instances)
instances.each do |instance|
# create instance if class is given
if instance.is_a?(Class)
klass = instance
# check the klass is extended
- raise Yuuki::Error, 'Runner instance must be extend Yuuki::Runner' unless klass.singleton_class.include?(Yuuki::Runner)
+ unless klass.singleton_class.include?(Yuuki::Runner)
+ raise Yuuki::Error, 'Runner instance must be extend Yuuki::Runner'
+ end
+
instance = instance.allocate
instance.instance_variable_set(:@yuuki, self)
instance.send(:initialize)
else
# check the klass is extended
- raise Yuuki::Error, 'Runner instance must be extend Yuuki::Runner' unless instance.class.singleton_class.include?(Yuuki::Runner)
+ unless instance.class.singleton_class.include?(Yuuki::Runner)
+ raise Yuuki::Error, 'Runner instance must be extend Yuuki::Runner'
+ end
+
# add @yuuki to the instance
instance.instance_variable_set(:@yuuki, self)
end
# regist
@@ -46,23 +54,23 @@
# returns runners
# @return [Array<[Method, Hash<Symbol, Object>]>]
def runners
list = @instances.flat_map do |instance|
methods = instance.class.instance_variable_get(:@yuuki_methods)
- methods.select{|_sig, meta| meta[:enabled]}.map{|sig, meta| [instance.method(sig), meta]}
+ methods.select {|_sig, meta| meta[:enabled]}.map {|sig, meta| [instance.method(sig), meta]}
end
- list.sort_by{|_method, meta| -(meta[:priority] || 0)}
+ list.sort_by {|_method, meta| -(meta[:priority] || 0)}
end
# returns all tags defined as Set
def tags
tags = @instances.flat_map do |instance|
methods = instance.class.instance_variable_get(:@yuuki_methods)
- methods.select{|_sig, meta| meta[:enabled]}.flat_map{|_sig, meta| meta[:tags]}
+ methods.select {|_sig, meta| meta[:enabled]}.flat_map {|_sig, meta| meta[:tags]}
end
ret = Set.new
- tags.each{|e| ret += e if e}
+ tags.each {|e| ret += e if e}
ret
end
# runs all methods
# @param [Object] args arguments
@@ -88,13 +96,14 @@
def run_tag(*tags, **args, &block)
t = self.tags
tags.each do |e|
next if t.include?(e)
raise Yuuki::Error, "tag `#{e}` is not associated" unless @ignore_tag_error
+
warn "Yuuki Warning: tag `#{e}` is not associated"
end
- run_select(proc{|_method, meta| meta[:tags]&.intersect?(tags)}, **args, &block)
+ run_select(proc {|_method, meta| meta[:tags]&.intersect?(tags)}, **args, &block)
end
# runs the specific method
# @param [Class, nil] klass
# @param [Symbol, nil] method_sig method name
@@ -140,30 +149,37 @@
end
def run_method_internal(method, args, &block)
params = method.parameters
return method[] if params.empty?
+
+ yoshinon = Yoshinon.lock if @use_yoshinon
params_array = []
params_hash = {}
params_block = nil
nonspecified_last_opt = nil
params.each do |type, name|
case type
when :req
- raise Yuuki::Error, "A required argument '#{name}' was not found on running #{method.owner}::#{method.name}" unless args.key?(name)
+ unless args.key?(name)
+ raise Yuuki::Error, "A required argument '#{name}' was not found on running #{method.owner}::#{method.name}"
+ end
+
params_array << args[name]
when :opt
# if parameters do not contain the :opt argument, treat it as not specified
next nonspecified_last_opt = name unless args.key?(name)
+
if nonspecified_last_opt
# if there already exist non-specified :opt arguments, no more specified :opt argument is allowed
raise Yuuki::Error, "A required argument '#{nonspecified_last_opt}' was not found"\
" on running #{method.owner}::#{method.name}"" with optional argument '#{name}'"
end
params_array << args[name]
when :rest
next unless args.key?(name)
+
if nonspecified_last_opt
# if there already exist non-specified :opt arguments, the :rest argument cannot be handled
raise Yuuki::Error, "A required argument '#{nonspecified_last_opt}' not found"\
" on running #{method.owner}::#{method.name}"" with rest argument '#{name}'"
end
@@ -171,25 +187,32 @@
params_array += args[name]
else
params_array << args[name]
end
when :keyreq
- raise Yuuki::Error, "A required key argument '#{name}' was not found on running #{method.owner}::#{method.name}" unless args.key?(name)
+ unless args.key?(name)
+ raise Yuuki::Error,
+ "A required key argument '#{name}' was not found on running #{method.owner}::#{method.name}"
+ end
+
params_hash[name] = args[name]
when :key
params_hash[name] = args[name] if args.key?(name)
when :keyrest
next unless args.key?(name)
+
if args[name].respond_to?(:to_hash)
params_hash.merge!(args[name])
else
params_hash[name] = args[name]
end
when :block
params_block = args[name]
end
end
- params_block = block unless params.any?{|type, _| type == :block}
+ params_block = block unless params.any? {|type, _| type == :block}
params_hash.empty? ? method[*params_array, ¶ms_block] : method[*params_array, **params_hash, ¶ms_block]
end
+ ensure
+ yoshinon&.unlock if @use_yoshinon
end
end