Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: compatibility with ruby 3.2 #299

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Metrics/ModuleLength:
- '**/test/**/*_test.rb'

Metrics/BlockLength:
ExcludedMethods:
AllowedMethods:
- describe
- it

Expand Down
5 changes: 5 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ Rake::TestTask.new("test:core") do |t|
.exclude("test/app/test_run.rb")
.exclude("test/interface/async/test_interface.rb")
end
test_files =
test_files
.exclude("test/interface/v1/**/*")
.exclude("test/interface/v2/**/*")
test_files = test_files.exclude("test/test_gui.rb") unless has_gui
t.test_files = test_files
t.warning = false
Expand All @@ -79,6 +83,7 @@ Rake::TestTask.new("test:interface:v2") do |t|
end

task "test" => "test:core"
task "test" => "test:interface:v1" unless RUBY_VERSION >= "3.0"
task "test" => "test:interface:v2"

task "rubocop" do
Expand Down
1 change: 1 addition & 0 deletions bin/roby-display
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ begin
Roby::CLI::Display.start(ARGV)
exit 0
rescue Interrupt
require "roby"
Roby.info "Interrupted by user"
exit 1
rescue Exception => e
Expand Down
2 changes: 1 addition & 1 deletion lib/roby/actions/models/interface_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ def method_missing(name, *args, **kw)

# Declare that this fault response table should be used on all plans
# that are going to use this action interface
def use_fault_response_table(table_model, arguments = {})
def use_fault_response_table(table_model, **arguments)
table_model.validate_arguments(arguments)
fault_response_tables << [table_model, arguments]
end
Expand Down
4 changes: 2 additions & 2 deletions lib/roby/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ def setup
self.planners.each do |planner|
if planner.respond_to?(:each_fault_response_table)
planner.each_fault_response_table do |table, arguments|
plan.use_fault_response_table table, arguments
plan.use_fault_response_table table, **arguments
end
end
end
Expand Down Expand Up @@ -1978,7 +1978,7 @@ def test_files_for(model)

test_files = []
model.definition_location.each do |location|
file = location.absolute_path
next unless (file = location.absolute_path)
next unless (base_path = find_base_path_for(file))

relative = Pathname.new(file).relative_path_from(base_path)
Expand Down
50 changes: 42 additions & 8 deletions lib/roby/app/cucumber/controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require "roby/interface/v1/async"

module Roby
module App
module Cucumber
Expand All @@ -25,6 +23,9 @@ class InvalidState < RuntimeError; end
# Actions that would be started by {#current_batch}
attr_reader :pending_actions

# The remote interface version to use
attr_accessor :interface_version

# Whether the process should abort when an error is detected, or
# keep running the actions as-is. The latter is useful for
# debugging
Expand All @@ -50,21 +51,52 @@ def roby_connected?
@roby_interface&.connected?
end

def self.roby_default_interface_version
if (v = ENV["ROBY_DEFAULT_INTERFACE_VERSION"])
Integer(v)
elsif RUBY_VERSION >= "3.0"
2
else
1
end
end

def self.roby_default_interface_port(version)
roby_interface_module(version)::DEFAULT_PORT
end

def self.roby_interface_module(version)
if version == 1
Roby::Interface::V1
else
Roby::Interface::V2
end
end

# @param [Integer] port the port through which we should connect
# to the Roby interface. Set to zero to pick a random port.
def initialize(
port: Roby::Interface::DEFAULT_PORT,
keep_running: (ENV["CUCUMBER_KEEP_RUNNING"] == "1"),
validation_mode: (ENV["ROBY_VALIDATE_STEPS"] == "1")
validation_mode: (ENV["ROBY_VALIDATE_STEPS"] == "1"),
interface_version: self.class.roby_default_interface_version,
port: self.class.roby_default_interface_port(interface_version)
)
require "roby/interface/v#{interface_version}/async"

@roby_pid = nil
@roby_port = port
@background_jobs = []
@keep_running = keep_running
@validation_mode = validation_mode
@interface_version = interface_version
@port = port
@pending_actions = []
end

def roby_interface_module
self.class.roby_interface_module(@interface_version)
end

# The object used to communicate with the Roby instance
#
# @return [Roby::Interface::V1::Async::Interface]
Expand All @@ -76,7 +108,7 @@ def roby_interface
end

@roby_interface ||=
Roby::Interface::V1::Async::Interface
roby_interface_module::Async::Interface
.new("localhost", port: @roby_port)
end

Expand Down Expand Up @@ -106,7 +138,8 @@ def roby_start(
options << "--log-dir=#{log_dir}" if log_dir
if @roby_port == 0
server = TCPServer.new("localhost", 0)
options << "--interface-fd=#{server.fileno}"
options <<
"--interface-v#{@interface_version}-fd=#{server.fileno}"
spawn_options = spawn_options.merge({ server => server })
@roby_port = server.local_address.ip_port
else
Expand All @@ -116,6 +149,7 @@ def roby_start(
Gem.ruby, File.join(Roby::BIN_DIR, "roby"), "run",
"--robot=#{robot_name},#{robot_type}",
"--controller",
"--interface-versions=#{@interface_version}",
"--quiet",
*options,
*state.map { |k, v| "--set=#{k}=#{v}" },
Expand Down Expand Up @@ -358,7 +392,7 @@ def __start_job(description, m, arguments, monitoring)
return
end

action = Interface::V1::Async::ActionMonitor.new(
action = roby_interface_module::Async::ActionMonitor.new(
roby_interface, m, arguments
)
action.restart(batch: current_batch)
Expand Down Expand Up @@ -434,7 +468,7 @@ def run_job(m, arguments = {})
return
end

action = Interface::V1::Async::ActionMonitor.new(
action = roby_interface_module::Async::ActionMonitor.new(
roby_interface, m, arguments
)
action.restart(batch: current_batch)
Expand Down
5 changes: 3 additions & 2 deletions lib/roby/app/debug.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require "stackprof"
require "rbtrace"
require "objspace"
require "roby/interface/core"

module Roby
module App
Expand All @@ -27,7 +28,7 @@ def stackprof_start(one_shot: false, cycles: nil, mode: :cpu, interval: nil, raw
else
1000
end
StackProf.start(mode: mode, interval: interval, raw: raw)
StackProf.start({ mode: mode, interval: interval, raw: raw })

if one_shot && !cycles
cycles = 1
Expand All @@ -48,7 +49,7 @@ def stackprof_start(one_shot: false, cycles: nil, mode: :cpu, interval: nil, raw
execution_engine.remove_propagation_handler(@cycle_counter_handler)
@cycle_counter_handler = nil
else
StackProf.start(mode: mode, interval: interval)
StackProf.start({ mode: mode, interval: interval })
end
end
end
Expand Down
40 changes: 27 additions & 13 deletions lib/roby/app/rake.rb
Original file line number Diff line number Diff line change
Expand Up @@ -805,29 +805,43 @@ def self.define_rubocop_if_enabled(
)
return false unless Rake.use_rubocop?

begin
require "rubocop/rake_task"
rescue LoadError
raise if required

return
if detect_rubocop?
define_rubocop(junit: junit, report_dir: report_dir)
elsif required
raise "rubocop required but not present"
end

define_rubocop(junit: junit, report_dir: report_dir)
true
end

def self.detect_rubocop?
# Do NOT use out: :close here, it breaks bundler in some ways
run_rubocop("--version", out: "/dev/null")
true
rescue Errno::ENOENT
false
end

def self.define_rubocop(
junit: Rake.use_junit?, report_dir: Rake.report_dir
)
require "rubocop/rake_task"
RuboCop::RakeTask.new do |t|
if junit
t.formatters << "junit"
t.options << "-o" << "#{report_dir}/rubocop.junit.xml"
end
options = []
if junit
options.concat(
["-f", "junit", "--out",
File.join(report_dir, "#{report_dir}/rubocop.junit.xml")]
)
end

::Rake::Task.define_task "rubocop" do
run_rubocop(*options)
end
end

def self.run_rubocop(*arguments, **options)
system(ENV["RUBOCOP_CMD"] || "rubocop", *arguments,
exception: true, **options)
end
end
end
end
6 changes: 5 additions & 1 deletion lib/roby/app/scripts/run.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@
app.log_create_current = false
end
opt.on "--interface-fd=FD", Integer,
"file descriptor to use for the interface server" do |fd|
"deprecated, use --interface-v1-fd instead" do |fd|
app.shell_interface_fd = fd
end
opt.on "--interface-v1-fd=FD", Integer,
"file descriptor to use for the v1 interface server" do |fd|
app.shell_interface_fd = fd
end
opt.on "--interface-v2-fd=FD", Integer,
Expand Down
1 change: 1 addition & 0 deletions lib/roby/cli/gen/app/.rubocop-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.64.1
3 changes: 3 additions & 0 deletions lib/roby/cli/gen/app/.rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
inherit_gem:
rubocop-rock: defaults.yml

AllCops:
NewCops: enable

2 changes: 1 addition & 1 deletion lib/roby/cli/gen/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def in_module(*module_path)
close_code = []
last_module_i = module_path.size - 1
module_path.each_with_index do |m, i|
nodoc = " #:nodoc:" if i == last_module_i
nodoc = " # :nodoc:" if i == last_module_i
open_code.push "#{indent}module #{m}#{nodoc}"
close_code.unshift "#{indent}end"
indent += " "
Expand Down
16 changes: 8 additions & 8 deletions lib/roby/cli/gen/roby_app/config/robots/robot.rb.erb
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
# frozen_string_literal: true

<% if robot_name != 'default' %>## A common pattern is to load the 'default' robot configuration
require_relative "./default"
require_relative "default"

<% end %>## One can require the configuration from another robot, for instance if one has
## a common robot class with minor modifications
#
# require 'config/robots/robot_class'

# Block evaluated at the very beginning of the Roby app initialization
Robot.init do
Robot.init do # rubocop:disable Lint/EmptyBlock
## Make models from another Roby app accessible
# Relative paths are resolved from the root of this app
# Roby.app.register_app('../separate_path')
end

# Block evaluated to configure the system, that is set up values in Roby's Conf
# and State
Robot.setup do
Robot.setup do # rubocop:disable Lint/EmptyBlock
end

# Block evaluated to load the models this robot requires
#
# This is called after `setup`
Robot.requires do
Robot.requires do # rubocop:disable Lint/EmptyBlock
end

# The opposite of 'setup' (and 'requires')
Robot.cleanup do
Robot.cleanup do # rubocop:disable Lint/EmptyBlock
end

# Setup of the robot's main action interface
Expand All @@ -40,17 +40,17 @@ end
#
# use_profile <%= Roby.app.module_name %>::Profiles::BaseProfile
#
Robot.actions do
Robot.actions do # rubocop:disable Lint/EmptyBlock
end

# Block evaluated when the Roby app is fully setup, and the robot ready to
# start. This is where one usually adds permanent tasks and/or status lines
Robot.controller do
Robot.controller do # rubocop:disable Lint/EmptyBlock
end

# Block evaluated right after the execution, but before the cleanup
#
# In particular, this is executed at teardown between each tests. Mostly, undo
# things here that the controller block would have registered.
Robot.shutdown do
Robot.shutdown do # rubocop:disable Lint/EmptyBlock
end
2 changes: 1 addition & 1 deletion lib/roby/coordination/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def attach_fault_response_tables_to(_task)
val
end
end
root_task.use_fault_response_table(table, arguments)
root_task.use_fault_response_table(table, **arguments)
end
end

Expand Down
8 changes: 1 addition & 7 deletions lib/roby/coordination/models/action_state_machine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,7 @@ def capture(state, event = nil, &block)
raise ArgumentError, "#{event} is not an event that is active in state #{state}"
end

filter =
if block
lambda(&block)
else
->(ev) { ev.context.first }
end

filter = block || ->(ev) { ev.context.first }
capture = Capture.new(filter)
captures[capture] = [state, event]
capture
Expand Down
2 changes: 1 addition & 1 deletion lib/roby/coordination/models/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def validate_event(object)

# Declare that this fault response table should be active as long as
# this coordination model is
def use_fault_response_table(table_model, arguments = {})
def use_fault_response_table(table_model, **arguments)
arguments = table_model.validate_arguments(arguments)
used_fault_response_tables << [table_model, arguments]
end
Expand Down
2 changes: 1 addition & 1 deletion lib/roby/droby/object_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def deregister_siblings(local_object, siblings)
# This registers the mapping for the local process (local_id =>
# local_object.droby_id), along with known siblings if provided
def register_object(local_object, known_siblings = {})
register_siblings(local_object, local_id => local_object.droby_id)
register_siblings(local_object, { local_id => local_object.droby_id })
register_siblings(local_object, known_siblings)
end

Expand Down
Loading