proc 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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