krpc 0.4.0.beta2 → 0.4.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1e7d575d4a1dbb6498787b0e82a39730f94f0d0d
4
- data.tar.gz: 79568d6c4d305a5921ebc5c4c646825ccf484f73
3
+ metadata.gz: 34cd7307210203562c7780105ae99214371fea14
4
+ data.tar.gz: 4088ab02a044dd1bef3b60ae94df0d60ec877bab
5
5
  SHA512:
6
- metadata.gz: c23caec29dd780b472326b178f914db6b9b6751c7e109d05df181c9cb3a45bc55cbecf2f0fff2f624f4ad7e2e67740285307ea000a3b3a76db574453a7463ac0
7
- data.tar.gz: 9b6725253fe71724ed3ceb2b22280a46bda329a339fb2d05b8bcda88f2fd6e5515883cd030547e8d326b3d8d3b06eb986cef375895a26a33b8f99eb17fcc4531
6
+ metadata.gz: 417a3bddec8125acbf6062fc3e2eaf520bc5edec63cc7738d984d658f631717eede00e3566f5880968e7019a0129912764c41d45cce1d8d7990ab53e28c9cd6f
7
+ data.tar.gz: a0dce5abd9b4729299ab70d5c4316408f68c95e8ad02722ca5d993e3221fa0e0abab5aeb66e6cf3efc48730a82b3c8d591e196bd6fd86179c638d8c94e1eac1d
data/README.md CHANGED
@@ -94,7 +94,7 @@ SpaceCenter.transform_position(
94
94
  to :ReferenceFrame - The reference frame to covert the position vector to.
95
95
  ) :Array[Float, Float, Float] - The corresponding position vector in reference frame to.
96
96
 
97
- Converts a position vector from one reference frame to another.
97
+ Converts a position vector from one reference frame to another.
98
98
  => nil
99
99
  ```
100
100
 
@@ -24,12 +24,12 @@ Gem::Specification.new do |s|
24
24
 
25
25
  s.required_ruby_version = ">= 2.1.0"
26
26
 
27
- s.add_runtime_dependency "google-protobuf", "~> 3.1"
27
+ s.add_runtime_dependency "google-protobuf", "~> 3.4"
28
28
  s.add_runtime_dependency "colorize", "~> 0.8"
29
- s.add_runtime_dependency "nokogiri", "~> 1.6"
30
- s.add_development_dependency "bundler", "~> 1.13"
31
- s.add_development_dependency "pry", "~> 0.10"
32
- s.add_development_dependency "rspec", "~> 3.5"
33
- s.add_development_dependency "rake", "~> 11.3"
29
+ s.add_runtime_dependency "nokogiri", "~> 1.8"
30
+ s.add_development_dependency "bundler", "~> 1.15"
31
+ s.add_development_dependency "pry", "~> 0.11"
32
+ s.add_development_dependency "rspec", "~> 3.6"
33
+ s.add_development_dependency "rake", "~> 12.1"
34
34
  s.add_development_dependency "hanna-nouveau", "~> 1.0"
35
35
  end
@@ -4,13 +4,13 @@ require 'krpc/client'
4
4
 
5
5
  module KRPC
6
6
  class << self
7
-
7
+
8
8
  # Connect to a kRPC server, generate services API and return Client object. If the block is
9
9
  # given, then it's called passing Client object and the connection to kRPC server is closed
10
10
  # at the end of the block.
11
11
  def connect(*args, &block)
12
12
  Client.new(*args).connect!(&block)
13
13
  end
14
-
14
+
15
15
  end
16
16
  end
@@ -9,11 +9,11 @@ require 'krpc/core_extensions'
9
9
  require 'krpc/krpc.pb'
10
10
 
11
11
  module KRPC
12
-
12
+
13
13
  ##
14
- # A kRPC client, through which all Remote Procedure Calls are made. To make RPC calls client
14
+ # A kRPC client, through which all Remote Procedure Calls are made. To make RPC calls client
15
15
  # must first connect to server. This can be achieved by calling Client#connect or Client#connect!
16
- # methods. Client object can connect and disconnect from the server many times during it's
16
+ # methods. Client object can connect and disconnect from the server many times during it's
17
17
  # lifetime. RPCs can be made by calling Client#execute_rpc method. After generating the services API
18
18
  # (with Client#generate_services_api! call), RPCs can be also made using
19
19
  # `client.service_name.procedure_name(parameter, ...)`
@@ -34,7 +34,7 @@ module KRPC
34
34
 
35
35
  attr_reader :name, :rpc_connection, :stream_connection, :streams_manager, :core
36
36
 
37
- # Create new Client object, optionally specifying IP address and port numbers on witch kRPC
37
+ # Create new Client object, optionally specifying IP address and port numbers on witch kRPC
38
38
  # server is listening and the name for this client.
39
39
  def initialize(name: DEFAULT_NAME, host: Connection::DEFAULT_SERVER_HOST, rpc_port: Connection::DEFAULT_SERVER_RPC_PORT, stream_port: Connection::DEFAULT_SERVER_STREAM_PORT)
40
40
  @name = name
@@ -45,10 +45,10 @@ module KRPC
45
45
  @core = Services::Core.new(self)
46
46
  Doc.add_docstring_info(false, self.class, "core", return_type: @core.class, xmldoc: "<doc><summary>Core kRPC service, e.g. for querying for the available services. Most of this functionality is used internally by the Ruby client and therefore does not need to be used directly from application code. This service is hardcoded (in kRPC Ruby client) version of 'krpc' service, so 1) it is available even before the services API is generated, but 2) can be out of sync with 'krpc' service.</summary></doc>")
47
47
  end
48
-
48
+
49
49
  # Connect to a kRPC server on the IP address and port numbers specified during this client
50
50
  # object creation and return `self`. Calling this method while the client is already connected
51
- # will raise an exception. If the block is given, then it's called passing `self` and the
51
+ # will raise an exception. If the block is given, then it's called passing `self` and the
52
52
  # connection to kRPC server is closed at the end of the block.
53
53
  def connect(&block)
54
54
  rpc_connection.connect
@@ -57,9 +57,9 @@ module KRPC
57
57
  call_block_and_close(block) if block_given?
58
58
  self
59
59
  end
60
-
60
+
61
61
  # Connect to a kRPC server, generate the services API and return `self`. Shorthand for calling
62
- # Client#connect and Client#generate_services_api! subsequently. If the block is given, then
62
+ # Client#connect and Client#generate_services_api! subsequently. If the block is given, then
63
63
  # it's called passing `self` and the connection to kRPC server is closed at the end of the block.
64
64
  def connect!(&block)
65
65
  connect
@@ -67,8 +67,8 @@ module KRPC
67
67
  call_block_and_close(block) if block_given?
68
68
  self
69
69
  end
70
-
71
- # Close connection to kRPC server. Returns `true` if the connection has closed or `false` if
70
+
71
+ # Close connection to kRPC server. Returns `true` if the connection has closed or `false` if
72
72
  # the client had been already disconnected.
73
73
  def close
74
74
  streams_manager.remove_all_streams
@@ -81,16 +81,16 @@ module KRPC
81
81
  def connected?
82
82
  rpc_connection.connected?
83
83
  end
84
-
85
- # Interrogates the server to find out what functionality it provides and dynamically creates
84
+
85
+ # Interrogates the server to find out what functionality it provides and dynamically creates
86
86
  # all of the classes and methods that form the services API. For each service that server provides:
87
- #
87
+ #
88
88
  # 1. Class `KRPC::Services::{service name here}`, and module `KRPC::Gen::{service name here}`
89
89
  # are created.
90
90
  # 2. `KRPC::Gen::{service name here}` module is filled with dynamically created classes.
91
91
  # 3. Those classes in turn are filled with dynamically created methods, which form the API for
92
92
  # this service.
93
- # 4. Instance method `{service name here}` is created in this client object that returns
93
+ # 4. Instance method `{service name here}` is created in this client object that returns
94
94
  # `KRPC::Services::{service name here}` object. This object is entry point for accessing
95
95
  # functionality provided by `{service name here}` service.
96
96
  #
@@ -108,7 +108,7 @@ module KRPC
108
108
  def generate_services_api!
109
109
  return self if services_api_generated?
110
110
  raise(Error, "Can't generate the services API while not connected to a server -- call Client#connect! to connect to server and generate the services API in one call") if not connected?
111
-
111
+
112
112
  resp = core.get_services
113
113
  resp.services.each do |service_msg|
114
114
  service_class = Services.create_service(service_msg)
@@ -122,17 +122,17 @@ module KRPC
122
122
  end
123
123
  self
124
124
  end
125
-
125
+
126
126
  # Returns `true` if the services API has been already generated, `false` otherwise.
127
127
  def services_api_generated?
128
128
  respond_to? :space_center or respond_to? :test_service
129
129
  end
130
-
130
+
131
131
  # Execute an RPC.
132
132
  def execute_rpc(service, procedure, args=[], kwargs={}, param_names=[], param_types=[], param_default=[], return_type: nil)
133
133
  send_request(service, procedure, args, kwargs, param_names, param_types, param_default)
134
134
  result = receive_result
135
- raise(RPCError, result.error) unless result.field_empty? :error
135
+ raise build_exception(result.error) unless result.field_empty? :error
136
136
  unless return_type.nil?
137
137
  Decoder.decode(result.value, return_type, self)
138
138
  else
@@ -143,13 +143,13 @@ module KRPC
143
143
  raise e
144
144
  end
145
145
 
146
- # Build a PB::Request object.
146
+ # Build an PB::Request object.
147
147
  def build_request(service, procedure, args=[], kwargs={}, param_names=[], param_types=[], param_default=[])
148
148
  call = build_procedure_call(service, procedure, args, kwargs, param_names, param_types, param_default)
149
149
  PB::Request.new(calls: [call])
150
150
  end
151
151
 
152
- # Build a PB::ProcedureCall object.
152
+ # Build an PB::ProcedureCall object.
153
153
  def build_procedure_call(service, procedure, args=[], kwargs={}, param_names=[], param_types=[], param_default=[])
154
154
  begin
155
155
  raise(ArgumentError, "param_names and param_types should be equal length\n\tparam_names = #{param_names}\n\tparam_types = #{param_types}") unless param_names.length == param_types.length
@@ -163,12 +163,20 @@ module KRPC
163
163
  PB::ProcedureCall.new(service: service, procedure: procedure, arguments: call_args)
164
164
  end
165
165
 
166
+ # Build an exception from an PB::Error object.
167
+ def build_exception(error)
168
+ msg = error.description
169
+ msg = "#{error.service}.#{error.name}: #{msg}" unless error.field_empty?(:service) || error.field_empty?(:name)
170
+ msg += "\nServer stack trace:\n#{error.stack_trace}" unless error.field_empty?(:stack_trace)
171
+ RPCError.new(msg)
172
+ end
173
+
166
174
  protected #----------------------------------
167
-
175
+
168
176
  def construct_arguments(args, kwargs, param_names, param_types, param_default, required_params_count)
169
177
  param_names_symbols = param_names.map(&:to_sym)
170
178
  kwargs_remaining = kwargs.count
171
-
179
+
172
180
  call_args = param_names_symbols.map.with_index do |name, i|
173
181
  is_kwarg = kwargs.has_key? name
174
182
  kwargs_remaining -= 1 if is_kwarg
@@ -194,7 +202,7 @@ module KRPC
194
202
  PB::Argument.new(position: i, value: v)
195
203
  end
196
204
  end.compact
197
-
205
+
198
206
  raise ArgumentErrorSig.new("keyword arguments for non existing parameters: #{(kwargs.keys - param_names_symbols).join(", ")}") unless kwargs_remaining == 0
199
207
  call_args
200
208
  end
@@ -203,16 +211,16 @@ module KRPC
203
211
  req = build_request(service, procedure, args, kwargs, param_names, param_types, param_default)
204
212
  rpc_connection.send_message req
205
213
  end
206
-
214
+
207
215
  def receive_result
208
216
  resp = rpc_connection.receive_message PB::Response
209
- raise(RPCError, resp.error) unless resp.field_empty? :error
217
+ raise build_exception(resp.error) unless resp.field_empty? :error
210
218
  resp.results[0]
211
219
  end
212
-
220
+
213
221
  def call_block_and_close(block)
214
222
  begin block.call(self) ensure close end
215
223
  end
216
-
224
+
217
225
  end
218
226
  end
@@ -10,18 +10,18 @@ module KRPC
10
10
  DEFAULT_SERVER_HOST = "127.0.0.1"
11
11
  DEFAULT_SERVER_RPC_PORT = 50000
12
12
  DEFAULT_SERVER_STREAM_PORT = 50001
13
-
13
+
14
14
  attr_reader :host, :port, :socket
15
-
15
+
16
16
  def initialize(host, port)
17
17
  @host, @port = host, port
18
18
  end
19
-
19
+
20
20
  # Connect and perform handshake.
21
21
  def connect
22
22
  if connected? then raise(ConnectionError, "Already connected")
23
- else
24
- @socket = TCPSocket.open(host, port)
23
+ else
24
+ @socket = TCPSocket.open(host, port)
25
25
  begin
26
26
  handshake
27
27
  rescue Exception => e
@@ -31,7 +31,7 @@ module KRPC
31
31
  end
32
32
  self
33
33
  end
34
-
34
+
35
35
  # Close connection and clean up.
36
36
  def close
37
37
  if connected?
@@ -40,29 +40,29 @@ module KRPC
40
40
  true
41
41
  else false end
42
42
  end
43
-
43
+
44
44
  # Return `true` if connected to a server, `false` otherwise.
45
45
  def connected?
46
46
  !socket.nil? && !socket.closed?
47
47
  end
48
-
48
+
49
49
  def handshake; end
50
50
  def cleanup; end
51
-
51
+
52
52
  def protobuf_handshake(type, **attrs)
53
53
  send_message PB::ConnectionRequest.new(type: type, **attrs)
54
54
  resp = receive_message PB::ConnectionResponse
55
55
  raise(ConnectionError, "#{resp.status} -- #{resp.message}") unless resp.status == :OK
56
56
  resp
57
57
  end
58
-
58
+
59
59
  def send(data)
60
60
  @socket.send(data, 0)
61
61
  end
62
62
  def send_message(msg)
63
63
  send Encoder.encode_message_with_size(msg)
64
64
  end
65
-
65
+
66
66
  def recv(maxlen = 1)
67
67
  maxlen == 0 ? "" : @socket.read(maxlen)
68
68
  end
@@ -88,7 +88,7 @@ module KRPC
88
88
  # TCP connection for sending RPC calls and retrieving its results.
89
89
  class RPCConnection < Connection
90
90
  attr_reader :name, :client_id
91
-
91
+
92
92
  def initialize(name = Client::DEFAULT_NAME, host = DEFAULT_SERVER_HOST, port = DEFAULT_SERVER_RPC_PORT)
93
93
  super host, port
94
94
  @name = name
@@ -99,7 +99,7 @@ module KRPC
99
99
  resp = protobuf_handshake(:RPC, client_name: name)
100
100
  @client_id = resp.client_identifier
101
101
  end
102
-
102
+
103
103
  def cleanup
104
104
  @client_id = nil
105
105
  end
@@ -109,17 +109,17 @@ module KRPC
109
109
  # TCP connection for streaming.
110
110
  class StreamConnection < Connection
111
111
  attr_reader :rpc_connection
112
-
112
+
113
113
  def initialize(rpc_connection, host = DEFAULT_SERVER_HOST, port = DEFAULT_SERVER_STREAM_PORT)
114
114
  super host, port
115
115
  @rpc_connection = rpc_connection
116
116
  end
117
-
117
+
118
118
  # Perform handshake with kRPC server, sending `client_id` retrieved from `rpc_connection`.
119
119
  def handshake
120
- raise(ConnectionError, "RPC connection must obtain client_id before stream connection can perform valid handshake - closing stream connection") if rpc_connection.client_id.nil?
120
+ raise(ConnectionError, "RPC connection must obtain client_id before stream connection can perform valid handshake - closing stream connection") if rpc_connection.client_id.nil?
121
121
  protobuf_handshake(:STREAM, client_identifier: rpc_connection.client_id)
122
122
  end
123
123
  end
124
-
124
+
125
125
  end
@@ -3,7 +3,7 @@ class Module
3
3
  def class_name
4
4
  name.rpartition("::").last
5
5
  end
6
-
6
+
7
7
  def const_get_or_create(module_name, value = nil, &block)
8
8
  return const_get(module_name) if const_defined?(module_name, false)
9
9
  value = block.call if block_given?
@@ -26,9 +26,9 @@ class String
26
26
  end
27
27
 
28
28
  def integer?
29
- Integer(self) != nil rescue false
29
+ Integer(self) != nil rescue false
30
30
  end
31
-
31
+
32
32
  def numeric?
33
33
  Float(self) != nil rescue false
34
34
  end
@@ -4,7 +4,7 @@ require 'set'
4
4
  module KRPC
5
5
  module Decoder
6
6
  class << self
7
-
7
+
8
8
  # Given a type object, and serialized data, decode the ruby value/object
9
9
  def decode(data, type, client)
10
10
  if type.is_a?(Types::MessageType) then type.ruby_type.decode(data)
@@ -33,12 +33,12 @@ module KRPC
33
33
  else raise(RuntimeError, "Cannot decode type #{type} from data: #{data}")
34
34
  end
35
35
  end
36
-
36
+
37
37
  def decode_value(data, type)
38
38
  type_string = type.is_a?(String) ? type : type.protobuf_type.code.to_s.downcase
39
- ProtobufUtils::Decoder.decode(data, type_string)
39
+ ProtobufUtils::Decoder.decode(data, type_string)
40
40
  end
41
-
41
+
42
42
  end
43
43
  end
44
44
  end
@@ -7,7 +7,7 @@ module KRPC
7
7
  @docstr_infos = {}
8
8
  @procedure_docstr_infos = {}
9
9
  class << self
10
-
10
+
11
11
  def docstring_for_method(method_owner, method_name, is_print_xmldoc_summary = true)
12
12
  is_static, class_cls = method_owner.class == Class ? [true, method_owner] : [false, method_owner.class]
13
13
  service_module_name, class_name = ruby_class_to_pb_module_class_pair(class_cls)
@@ -16,10 +16,10 @@ module KRPC
16
16
  construct_docstring(*@docstr_infos[key], true, is_static, is_print_xmldoc_summary)
17
17
  else
18
18
  "No docstring for #{class_cls.name}#{calc_separator(is_static)}#{method_name.to_s} method" +
19
- (method_owner.respond_to?(method_name) ? "" : "\nThere is no such method -- maybe a typo")
19
+ (method_owner.respond_to?(method_name) ? "" : "\nThere is no such method -- maybe a typo?")
20
20
  end
21
21
  end
22
-
22
+
23
23
  def docstring_for_procedure(service_name, procedure_name, is_print_xmldoc_summary = true)
24
24
  key = [service_name, procedure_name].hash
25
25
  if @procedure_docstr_infos.has_key? key
@@ -40,30 +40,30 @@ module KRPC
40
40
  @docstr_infos[key2] = val
41
41
  end
42
42
  end
43
-
43
+
44
44
  def add_special_docstring_info(key, value)
45
45
  @docstr_infos[key] = value
46
46
  end
47
-
47
+
48
48
  private #----------------------------------
49
-
49
+
50
50
  def ruby_class_to_pb_module_class_pair(ruby_class)
51
51
  return ["", Client.class_name] if ruby_class == Client
52
52
  rest, _, pb_class_name = ruby_class.name.rpartition("::")
53
53
  _, _, pb_service_name = rest.rpartition("::")
54
54
  [pb_service_name, pb_class_name]
55
55
  end
56
-
56
+
57
57
  def calc_separator(is_static)
58
58
  is_static ? '.' : '#'
59
59
  end
60
-
60
+
61
61
  def construct_docstring(namespace, separator, name, param_names, param_types, param_default, return_type, xmldoc, is_hide_this_param, is_prepend_client_param, is_print_xmldoc_summary)
62
62
  xmldoc = Nokogiri::XML(xmldoc)
63
63
  xmldoc_summary = xmlElements2str(xmldoc.xpath("doc/summary").children, :light_blue, :light_green, :light_red)
64
64
 
65
65
  xmldoc_returns = xmlElements2str(xmldoc.xpath("doc/returns").children, :blue, :green, :light_red)
66
- xmldoc_returns = "- ".blue + xmldoc_returns unless xmldoc_returns.empty?
66
+ xmldoc_returns = "- ".blue + xmldoc_returns unless xmldoc_returns.empty?
67
67
 
68
68
  xmldoc_params = {}
69
69
  xmldoc.xpath("doc/param").each do |e|
@@ -76,10 +76,10 @@ module KRPC
76
76
  end
77
77
  end
78
78
  end
79
-
79
+
80
80
  param_infos = param_names.zip(param_types.map{|x| type2str(x)}, param_default)
81
81
  param_infos.shift if is_hide_this_param && param_names[0] == "this"
82
- param_infos.unshift ["client", "Client", :no_default_value] if is_prepend_client_param
82
+ param_infos.unshift ["client", "Client", :no_default_value] if is_prepend_client_param
83
83
  if param_infos.empty?
84
84
  params = ""
85
85
  else
@@ -92,14 +92,14 @@ module KRPC
92
92
  "#{namespace.cyan}#{separator.cyan}#{name.bold}(#{params}) :#{type2str(return_type).light_red} #{xmldoc_returns}" \
93
93
  + (is_print_xmldoc_summary ? "\n\n#{xmldoc_summary}" : "")
94
94
  end
95
-
95
+
96
96
  def type2str(type)
97
97
  return "nil" if type.nil?
98
98
  return type.class_name if type.class == Class
99
99
  rt = type.ruby_type
100
100
  if type.is_a?(Types::EnumType) then "Enum" + rt.keys.to_s
101
101
  elsif type.is_a?(Types::ListType) ||
102
- type.is_a?(Types::SetType)
102
+ type.is_a?(Types::SetType)
103
103
  "#{rt.class_name}[#{type2str(type.value_type)}]"
104
104
  elsif type.is_a?(Types::DictionaryType)
105
105
  %Q{#{rt.class_name}[#{type2str(type.key_type)} => #{type2str(type.value_type)}]}
@@ -107,7 +107,7 @@ module KRPC
107
107
  %Q{#{rt.class_name}[#{type.value_types.map{|x| type2str(x)}.join(", ")}]}
108
108
  else rt.class_name end
109
109
  end
110
-
110
+
111
111
  def xmlElements2str(elements, main_color, paramref_color, value_color, error_color = :red)
112
112
  elements.map do |elem|
113
113
  if elem.is_a?(Nokogiri::XML::Text)
@@ -138,13 +138,13 @@ module KRPC
138
138
  elem.text.gsub("null","nil").colorize(value_color)
139
139
  else elem.to_s.colorize(error_color)
140
140
  end
141
- rescue RuntimeException => exc
141
+ rescue RuntimeException
142
142
  elem.to_s.colorize(error_color)
143
143
  end
144
144
  end
145
145
  end.join.gsub("\n"," ").gsub("!n!","\n").squeeze(' ').strip.gsub("!s!"," ")
146
146
  end
147
-
147
+
148
148
  def is_method_defined(path_array)
149
149
  method_name = path_array[-1].underscore
150
150
  begin
@@ -154,23 +154,18 @@ module KRPC
154
154
  false
155
155
  end
156
156
  end
157
-
157
+
158
158
  end
159
-
160
-
159
+
160
+
161
161
  module SuffixMethods
162
162
  DOCSTRING_SUFFIX = "_doc"
163
163
  DOCSTRING_SUFFIX_REGEX = /^(.+)(?:#{DOCSTRING_SUFFIX}(=)?)$/
164
-
164
+
165
165
  def self.included(base)
166
- base.extend self
167
- class << base
168
- def krpc_name
169
- class_name
170
- end
171
- end
166
+ base.extend self, ClassMethods
172
167
  end
173
-
168
+
174
169
  def method_missing(method, *args, &block)
175
170
  if DOCSTRING_SUFFIX_REGEX =~ method.to_s
176
171
  documented_method_name = $1 + $2.to_s
@@ -180,14 +175,20 @@ module KRPC
180
175
  end
181
176
  super
182
177
  end
183
-
178
+
184
179
  def respond_to_missing?(method, *)
185
180
  if DOCSTRING_SUFFIX_REGEX =~ method.to_s
186
181
  return true if respond_to? ($1 + $2.to_s).to_sym
187
182
  end
188
183
  super
189
184
  end
185
+
186
+ module ClassMethods
187
+ def krpc_name
188
+ class_name
189
+ end
190
+ end
190
191
  end
191
-
192
+
192
193
  end
193
194
  end