proc 0.12.0 → 0.14.0

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
  SHA256:
3
- metadata.gz: b102aa8b4a6c4f99758cab2f6aefff1800948b60197d920f6279cb76f26decbb
4
- data.tar.gz: 37b8a0aa99c4089a584b2b7197ab7e9e9ec7bc555a59bdaf1bbce76f4ab466ac
3
+ metadata.gz: 4fd5089ba0458dc13c198de1322bfc510a54157ef0ec49f957efa730b6de768e
4
+ data.tar.gz: d4c05363b54d8ae4607890b9ab552eb9ba3fc486c39251dcaac028aee29e21b7
5
5
  SHA512:
6
- metadata.gz: 33e2381e9f9d5ff7a6ff10c7ad4a75cc2d0687a4e6890916d4443563ddcaf883d7205b971e7dee63637f81731cea2c5caf80df1a980718db65c78b94db19c0ca
7
- data.tar.gz: fc7497fce516a9b003ed4dbf617d26c9c7ca5e6b2696f324cba275f765f85f6f878baaea2e7006d3e2e023a61de73b506aff743d1d3ae1451fa9226c2c9040d4
6
+ metadata.gz: 11793b5496575f947eb481b53732310b47d6a5fa5601e0826cc2dcc5f79fec498712abeaf14c9be82c683da519e1b9c785b7265e8d1f86e0027178aae6a606f6
7
+ data.tar.gz: c24ea2e3ef4337788c13cd53b373815e621c2cac9b504015672206c7e57dc7f9cef18b4deb94563eab0f4c9a536802f693687433b5cb21cb98222c2ced48b7db
data/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ ## [v0.14.0](https://github.com/metabahn/proc/releases/tag/2021-09-22)
2
+
3
+ *released on 2021-09-22*
4
+
5
+ * `chg` [#14](https://github.com/metabahn/proc/pull/14) Change Ruby client error handling to fallback to returning a result ([bryanp](https://github.com/bryanp))
6
+
7
+ ## [v0.13.0](https://github.com/metabahn/proc/releases/tag/2021-09-15)
8
+
9
+ *released on 2021-09-15*
10
+
11
+ * `chg` [#10](https://github.com/metabahn/proc/pull/10) Extract proc-composer from the proc client library for ruby ([bryanp](https://github.com/bryanp))
12
+ * `chg` [#7](https://github.com/metabahn/proc/pull/7) Update Ruby client to call api.proc.dev ([bryanp](https://github.com/bryanp))
13
+ * `add` [#3](https://github.com/metabahn/proc/pull/3) Introduce global authorization/instance to the Ruby client ([bryanp](https://github.com/bryanp))
14
+
15
+ ## [v0.12.1](https://github.com/metabahn/proc/releases/tag/2021-05-13)
16
+
17
+ *released on 2021-05-13*
18
+
19
+ * `chg` [#2](https://github.com/metabahn/proc/pull/2) Update http.rb dependency ([bryanp](https://github.com/bryanp))
20
+
21
+
data/lib/proc/callable.rb CHANGED
@@ -1,19 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Proc
4
- class Callable < BasicObject
5
- attr_reader :proc, :input, :arguments
6
-
7
- def initialize(proc, client:, input: ::Proc.undefined, arguments: {})
8
- @proc = proc.to_s
4
+ class Callable < Composer::Callable
5
+ def initialize(proc, client:, **kwargs)
9
6
  @client = client
10
- @input = input
11
- @arguments = arguments
12
- end
13
7
 
14
- def initialize_copy(_)
15
- @input = input.dup
16
- @arguments = arguments.dup
8
+ super(proc, **kwargs)
17
9
  end
18
10
 
19
11
  # [public] Dispatches this callable context to proc using the client.
@@ -25,12 +17,7 @@ class Proc
25
17
  arguments[:proc] = yield
26
18
  end
27
19
 
28
- callable = ::Proc::Callable.new(
29
- @proc,
30
- client: @client,
31
- input: input_omitted ? @input : input,
32
- arguments: @arguments.merge(arguments)
33
- )
20
+ callable = build_callable(input: input_omitted ? @input : input, arguments: @arguments.merge(arguments))
34
21
 
35
22
  @client.call(@proc, callable.input, **callable.arguments)
36
23
  end
@@ -38,132 +25,17 @@ class Proc
38
25
  # [public] Dispatches this callable context to proc using the client, calling the given block once for each value.
39
26
  #
40
27
  def each(input = input_omitted = true, **arguments, &block)
41
- callable = ::Proc::Callable.new(
42
- @proc,
43
- client: @client,
44
- input: input_omitted ? @input : input,
45
- arguments: @arguments.merge(arguments)
46
- )
28
+ callable = build_callable(input: input_omitted ? @input : input, arguments: @arguments.merge(arguments))
47
29
 
48
30
  @client.call(@proc, callable.input, **callable.arguments, &block)
49
31
  end
50
32
 
51
- # [public] Creates a new callable context based on this one, with a new input and/or arguments.
52
- #
53
- def with(input = input_omitted = true, **arguments)
54
- if ::Kernel.block_given?
55
- arguments[:proc] = yield
56
- end
57
-
58
- ::Proc::Callable.new(
59
- @proc,
60
- client: @client,
61
- input: input_omitted ? @input : input,
62
- arguments: @arguments.merge(arguments)
63
- )
64
- end
65
-
66
- # [public] Returns a composition built from this callable context and one or more other callables.
67
- #
68
- def compose(*others)
69
- composed = ::Proc::Composition.new(client: @client, input: @input)
70
- composed << self
71
- others.each { |other| composed << other }
72
- composed
73
- end
74
-
75
- # [public] Returns a composition built from this callable context and another callable.
76
- #
77
- def >>(other)
78
- composed = ::Proc::Composition.new(client: @client, input: @input)
79
- composed << self
80
- composed << other
81
- composed
82
- end
83
-
84
- def serialize(unwrapped: false)
85
- serialized = ["()", @proc]
86
-
87
- unless ::Proc.undefined?(@input)
88
- serialized << [">>", serialized_input]
89
- end
90
-
91
- serialized.concat(serialized_arguments)
92
-
93
- if unwrapped
94
- serialized
95
- else
96
- ["{}", serialized]
97
- end
33
+ private def build_callable(input:, arguments:, proc: @proc)
34
+ ::Proc::Callable.new(proc, client: @client, input: input, arguments: arguments)
98
35
  end
99
36
 
100
- def serialized_input
101
- serialize_value(@input)
102
- end
103
-
104
- def serialized_arguments
105
- @arguments.map { |key, value|
106
- ["$$", key.to_s, serialize_value(value)]
107
- }
108
- end
109
-
110
- # [public] Returns a callable context for `proc`, nested within this callable context.
111
- #
112
- def [](proc)
113
- arguments = if ::Kernel.block_given?
114
- duped = @arguments.dup
115
- duped[:proc] = yield
116
- duped
117
- else
118
- @arguments
119
- end
120
-
121
- ::Proc::Callable.new(
122
- [@proc, proc].join("."),
123
- client: @client,
124
- input: @input,
125
- arguments: arguments
126
- )
127
- end
128
-
129
- IGNORE_MISSING = %i[to_hash].freeze
130
-
131
- # [public] Allows nested callable contexts to be built through method lookups.
132
- #
133
- def method_missing(name, input = input_omitted = true, **arguments)
134
- if IGNORE_MISSING.include?(name)
135
- super
136
- else
137
- if ::Kernel.block_given?
138
- arguments[:proc] = yield
139
- end
140
-
141
- ::Proc::Callable.new(
142
- [@proc, name].join("."),
143
- client: @client,
144
- input: input_omitted ? @input : input,
145
- arguments: @arguments.merge(arguments)
146
- )
147
- end
148
- end
149
-
150
- def respond_to_missing?(name, *)
151
- if IGNORE_MISSING.include?(name)
152
- super
153
- else
154
- true
155
- end
156
- end
157
-
158
- private def serialize_value(value)
159
- case value
160
- when ::Symbol
161
- ["@@", value.to_s, {}]
162
- when ::Proc::Argument, ::Proc::Callable, ::Proc::Composition
163
- value.serialize
164
- else
165
- ["%%", value]
166
- end
37
+ private def build_composition(input:)
38
+ ::Proc::Composition.new(client: @client, input: input)
167
39
  end
168
40
  end
169
41
  end
data/lib/proc/client.rb CHANGED
@@ -1,14 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "core/async"
4
+ require "core/global"
5
+
4
6
  require "http"
5
7
  require "msgpack"
6
8
 
9
+ require "proc/composer"
10
+
7
11
  require_relative "msgpack/types/decimal"
8
12
  MessagePack::DefaultFactory.register_type(0x00, Proc::Msgpack::Types::Decimal)
9
13
  MessagePack::DefaultFactory.register_type(-1, Time, packer: MessagePack::Time::Packer, unpacker: MessagePack::Time::Unpacker)
10
14
 
11
- require_relative "argument"
12
15
  require_relative "callable"
13
16
  require_relative "composition"
14
17
  require_relative "enumerator"
@@ -57,7 +60,22 @@ class Proc
57
60
  # [public] Connection to proc, configured with an authorization.
58
61
  #
59
62
  class Client < BasicObject
63
+ class << self
64
+ def authorization
65
+ ::ENV.fetch("PROC_AUTH") {
66
+ auth_file_path = ::Pathname.new("~/.proc/auth").expand_path
67
+
68
+ if auth_file_path.exist?
69
+ auth_file_path.read
70
+ else
71
+ ""
72
+ end
73
+ }.strip
74
+ end
75
+ end
76
+
60
77
  include ::Is::Async
78
+ include ::Is::Global
61
79
 
62
80
  # [public] The configured authorization.
63
81
  #
@@ -82,7 +100,7 @@ class Proc
82
100
  "content-type" => "application/vnd.proc+msgpack"
83
101
  }.freeze
84
102
 
85
- def initialize(authorization, scheme: "https", host: "proc.dev")
103
+ def initialize(authorization = ::Proc::Client.authorization, scheme: "https", host: "api.proc.dev")
86
104
  @authorization = authorization
87
105
  @scheme = scheme
88
106
  @host = host
@@ -135,10 +153,10 @@ class Proc
135
153
  #
136
154
  # If a block is passed and the proc returns an enumerable, the block will be called with each value.
137
155
  #
138
- def call(proc = nil, input = ::Proc.undefined, **arguments, &block)
156
+ def call(proc = nil, input = ::Proc::Composer.undefined, **arguments, &block)
139
157
  body = []
140
158
 
141
- unless ::Proc.undefined?(input)
159
+ unless ::Proc::Composer.undefined?(input)
142
160
  body << [">>", serialize_value(input)]
143
161
  end
144
162
 
@@ -146,30 +164,13 @@ class Proc
146
164
  body << ["$$", key.to_s, serialize_value(value)]
147
165
  end
148
166
 
167
+ process(proc: proc, body: body, input: input, arguments: arguments, &block)
168
+ end
169
+
170
+ private def process(proc:, body:, input:, arguments:, &block)
149
171
  status, headers, payload = get_payload(proc: proc, body: body)
150
172
 
151
173
  case status
152
- when 200
153
- result = extract_output(payload)
154
-
155
- if (cursor = headers["x-cursor"])
156
- enumerator = if cursor.empty?
157
- ::Proc::Enumerator.new(result)
158
- else
159
- ::Proc::Enumerator.new(result) {
160
- arguments[:cursor] = cursor.to_s
161
- call(proc, input, **arguments)
162
- }
163
- end
164
-
165
- if block
166
- enumerator.each(&block)
167
- else
168
- enumerator
169
- end
170
- else
171
- result
172
- end
173
174
  when 400
174
175
  ::Kernel.raise ::Proc::Invalid, extract_error_message(payload)
175
176
  when 401
@@ -189,7 +190,30 @@ class Proc
189
190
  when 508
190
191
  ::Kernel.raise ::Proc::Error, extract_error_message(payload)
191
192
  else
192
- ::Kernel.raise ::Proc::Error, "unhandled"
193
+ result = extract_output(payload)
194
+
195
+ if !result.nil?
196
+ if (cursor = headers["x-cursor"])
197
+ enumerator = if cursor.empty?
198
+ ::Proc::Enumerator.new(result)
199
+ else
200
+ ::Proc::Enumerator.new(result) {
201
+ arguments[:cursor] = cursor.to_s
202
+ call(proc, input, **arguments)
203
+ }
204
+ end
205
+
206
+ if block
207
+ enumerator.each(&block)
208
+ else
209
+ enumerator
210
+ end
211
+ else
212
+ result
213
+ end
214
+ elsif (error = extract_error_message(payload))
215
+ ::Kernel.raise ::Proc::Error, error
216
+ end
193
217
  end
194
218
  end
195
219
 
@@ -210,7 +234,7 @@ class Proc
210
234
  # [public] Builds a named argument with options.
211
235
  #
212
236
  def argument(name, **options)
213
- ::Proc::Argument.new(name, **options)
237
+ ::Proc::Composer::Argument.new(name, **options)
214
238
  end
215
239
  alias_method :arg, :argument
216
240
 
@@ -222,7 +246,7 @@ class Proc
222
246
  case value
223
247
  when ::Symbol
224
248
  ["@@", value.to_s, {}]
225
- when ::Proc::Argument, ::Proc::Callable, ::Proc::Composition
249
+ when ::Proc::Composer::Argument, ::Proc::Callable, ::Proc::Composition
226
250
  value.serialize
227
251
  else
228
252
  ["%%", value]
@@ -1,18 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Proc
4
- class Composition
5
- attr_reader :input, :callables, :arguments
6
-
7
- def initialize(client:, input:, callables: [], arguments: {})
4
+ class Composition < Composer::Composition
5
+ def initialize(client:, **kwargs)
8
6
  @client = client
9
- @input = input
10
- @callables = callables
11
- @arguments = arguments
12
- end
13
7
 
14
- def initialize_copy(_)
15
- @callables = @callables.dup
8
+ super(**kwargs)
16
9
  end
17
10
 
18
11
  # [public] Dispatches this composition to proc using the client.
@@ -22,105 +15,29 @@ class Proc
22
15
  arguments[:proc] = yield
23
16
  end
24
17
 
25
- callable = self.class.new(
26
- client: @client,
18
+ callable = build_composition(
27
19
  input: input_omitted ? @input : input,
28
- callables: @callables.dup,
29
- arguments: @arguments.merge(arguments)
20
+ arguments: @arguments.merge(arguments),
21
+ callables: @callables.dup
30
22
  )
31
23
 
32
- @client.call("core.exec", Proc.undefined, proc: callable)
24
+ @client.call("core.exec", Proc::Composer.undefined, proc: callable)
33
25
  end
34
26
 
35
27
  # [public] Dispatches this composition to proc using the client, calling the given block once for each value.
36
28
  #
37
29
  def each(input = input_omitted = true, **arguments, &block)
38
- callable = self.class.new(
30
+ callable = build_composition(
39
31
  client: @client,
40
32
  input: input_omitted ? @input : input,
41
- callables: @callables.dup,
42
33
  arguments: @arguments.merge(arguments)
43
34
  )
44
35
 
45
- @client.call("core.exec", Proc.undefined, proc: callable, &block)
36
+ @client.call("core.exec", Proc::Composer.undefined, proc: callable, &block)
46
37
  end
47
38
 
48
- # [public] Creates a new composition based on this one, with a new input and/or arguments.
49
- #
50
- def with(input = input_omitted = true, **arguments)
51
- if block_given?
52
- arguments[:proc] = yield
53
- end
54
-
55
- self.class.new(
56
- client: @client,
57
- input: input_omitted ? @input : input,
58
- callables: @callables.dup,
59
- arguments: @arguments.merge(arguments)
60
- )
61
- end
62
-
63
- # [public] Returns a composition from this composition and one or more other callables.
64
- #
65
- def compose(*others)
66
- composed = dup
67
- others.each { |other| composed << other }
68
- composed
69
- end
70
-
71
- # [public] Returns a composition built from this composition and another callable.
72
- #
73
- def >>(other)
74
- composed = dup
75
- composed << other
76
- composed
77
- end
78
-
79
- def <<(callable)
80
- case callable
81
- when Composition
82
- merge(callable)
83
- when Callable
84
- @callables << callable
85
- end
86
- end
87
-
88
- def serialize
89
- serialized = ["{}"]
90
-
91
- unless Proc.undefined?(@input)
92
- serialized << [">>", serialized_input]
93
- end
94
-
95
- serialized + serialized_arguments + @callables.map { |callable| callable.serialize(unwrapped: true) }
96
- end
97
-
98
- def serialized_input
99
- serialize_value(@input)
100
- end
101
-
102
- def serialized_arguments
103
- @arguments.map { |key, value|
104
- ["$$", key.to_s, serialize_value(value)]
105
- }
106
- end
107
-
108
- def merge(composition)
109
- raise ArgumentError, "expected a composition" unless composition.is_a?(self.class)
110
-
111
- @callables.concat(composition.callables)
112
- @arguments.merge!(composition.arguments)
113
- end
114
-
115
- private def serialize_value(value)
116
- case value
117
- when Symbol
118
- ["@@", value.to_s, {}]
119
- when Argument, Callable, Composition
120
- value.serialize
121
- else
122
- ["%%", value]
123
- end
39
+ private def build_composition(callables:, input:, arguments:)
40
+ self.class.new(client: @client, input: input, callables: callables, arguments: arguments)
124
41
  end
125
42
  end
126
43
  end
data/lib/proc/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Proc
4
- VERSION = "0.12.0"
4
+ VERSION = "0.14.0"
5
5
 
6
6
  # [public]
7
7
  #
data/lib/proc.rb CHANGED
@@ -7,16 +7,8 @@ class Proc
7
7
  class << self
8
8
  # [public] Connect a client with an authorization.
9
9
  #
10
- def connect(authorization, **options)
11
- Client.new(authorization, **options)
12
- end
13
-
14
- def undefined
15
- @_undefined ||= ::Object.new
16
- end
17
-
18
- def undefined?(value)
19
- value == undefined
10
+ def connect(authorization = Proc::Client.authorization, client: Proc::Client, **options)
11
+ client.new(authorization, **options)
20
12
  end
21
13
  end
22
14
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Powell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-06 00:00:00.000000000 Z
11
+ date: 2021-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: core-async
@@ -16,28 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.5.0
19
+ version: '0.6'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.5.0
26
+ version: '0.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: core-global
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.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.0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: http
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '4.4'
47
+ version: '5.0'
34
48
  type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '4.4'
54
+ version: '5.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: msgpack
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -52,16 +66,30 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '1.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: proc-composer
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.0'
55
83
  description: Proc client library.
56
84
  email: bryan@metabahn.com
57
85
  executables: []
58
86
  extensions: []
59
87
  extra_rdoc_files: []
60
88
  files:
89
+ - CHANGELOG.md
61
90
  - LICENSE
62
91
  - README.md
63
92
  - lib/proc.rb
64
- - lib/proc/argument.rb
65
93
  - lib/proc/callable.rb
66
94
  - lib/proc/client.rb
67
95
  - lib/proc/composition.rb
@@ -87,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
115
  - !ruby/object:Gem::Version
88
116
  version: '0'
89
117
  requirements: []
90
- rubygems_version: 3.2.15
118
+ rubygems_version: 3.2.22
91
119
  signing_key:
92
120
  specification_version: 4
93
121
  summary: Proc client library.
data/lib/proc/argument.rb DELETED
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Proc
4
- class Argument
5
- def initialize(name, **options)
6
- @name = name
7
- @options = options
8
- end
9
-
10
- def serialize
11
- ["@@", @name.to_s, serialized_options]
12
- end
13
-
14
- def serialized_options
15
- @options.each_pair.each_with_object({}) { |(key, value), hash|
16
- hash[key.to_s] = serialize_value(value)
17
- }
18
- end
19
-
20
- private def serialize_value(value)
21
- if value.respond_to?(:serialize)
22
- value.serialize
23
- else
24
- ["%%", value]
25
- end
26
- end
27
- end
28
- end