trailblazer-developer 0.0.26 → 0.0.28
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 +4 -4
- data/.github/workflows/ci.yml +3 -4
- data/CHANGES.md +35 -0
- data/Gemfile +7 -4
- data/lib/trailblazer/developer/introspect/graph.rb +83 -0
- data/lib/trailblazer/developer/introspect.rb +17 -0
- data/lib/trailblazer/developer/render/circuit.rb +6 -49
- data/lib/trailblazer/developer/render/linear.rb +1 -1
- data/lib/trailblazer/developer/render/task_wrap.rb +79 -0
- data/lib/trailblazer/developer/trace/debugger/normalizer.rb +68 -0
- data/lib/trailblazer/developer/trace/debugger.rb +72 -0
- data/lib/trailblazer/developer/trace/present.rb +25 -43
- data/lib/trailblazer/developer/trace/stack.rb +21 -0
- data/lib/trailblazer/developer/trace/tree.rb +86 -0
- data/lib/trailblazer/developer/trace.rb +51 -112
- data/lib/trailblazer/developer/version.rb +1 -1
- data/lib/trailblazer/developer/wtf/renderer.rb +15 -16
- data/lib/trailblazer/developer/wtf.rb +44 -57
- data/lib/trailblazer/developer.rb +8 -2
- data/trailblazer-developer.gemspec +3 -2
- metadata +28 -10
- data/gems.local.rb +0 -11
- data/lib/trailblazer/developer/trace/focusable.rb +0 -78
- data/lib/trailblazer/developer/trace/inspector.rb +0 -48
@@ -1,16 +1,12 @@
|
|
1
|
-
require 'trailblazer/activity'
|
2
|
-
|
3
1
|
module Trailblazer::Developer
|
4
2
|
module Trace
|
5
3
|
|
6
|
-
Activity = Trailblazer::Activity
|
7
|
-
|
8
4
|
class << self
|
9
5
|
# Public entry point to activate tracing when running {activity}.
|
10
6
|
def call(activity, (ctx, flow_options), **circuit_options)
|
11
7
|
activity, (ctx, flow_options), circuit_options = Trace.arguments_for_call( activity, [ctx, flow_options], **circuit_options ) # only run once for the entire circuit!
|
12
8
|
|
13
|
-
signal, (ctx, flow_options) = Activity::TaskWrap.invoke(activity, [ctx, flow_options], **circuit_options)
|
9
|
+
signal, (ctx, flow_options) = Trailblazer::Activity::TaskWrap.invoke(activity, [ctx, flow_options], **circuit_options)
|
14
10
|
|
15
11
|
return flow_options[:stack], signal, [ctx, flow_options]
|
16
12
|
end
|
@@ -19,21 +15,20 @@ module Trailblazer::Developer
|
|
19
15
|
|
20
16
|
def arguments_for_call(activity, (options, original_flow_options), **original_circuit_options)
|
21
17
|
default_flow_options = {
|
22
|
-
stack:
|
23
|
-
|
24
|
-
|
25
|
-
output_data_collector: Trace.method(:default_output_data_collector),
|
18
|
+
stack: Trace::Stack.new,
|
19
|
+
input_data_collector: Trace.method(:default_input_data_collector),
|
20
|
+
output_data_collector: Trace.method(:default_output_data_collector),
|
26
21
|
}
|
27
22
|
|
28
|
-
flow_options = {
|
23
|
+
flow_options = {**default_flow_options, **Hash(original_flow_options)}
|
29
24
|
|
30
25
|
default_circuit_options = {
|
31
|
-
wrap_runtime: ::Hash.new(Trace.
|
26
|
+
wrap_runtime: ::Hash.new(Trace.task_wrap_extensions), # DISCUSS: this overrides existing {:wrap_runtime}.
|
32
27
|
}
|
33
28
|
|
34
|
-
circuit_options = {
|
29
|
+
circuit_options = {**original_circuit_options, **default_circuit_options}
|
35
30
|
|
36
|
-
return activity, [
|
31
|
+
return activity, [options, flow_options], circuit_options
|
37
32
|
end
|
38
33
|
end
|
39
34
|
|
@@ -42,16 +37,10 @@ module Trailblazer::Developer
|
|
42
37
|
# and before the TaskWrap is finished.
|
43
38
|
#
|
44
39
|
# @private
|
45
|
-
def
|
46
|
-
Activity::TaskWrap
|
47
|
-
|
48
|
-
|
49
|
-
row: Activity::TaskWrap::Pipeline.Row("task_wrap.capture_args", Trace.method(:capture_args))
|
50
|
-
},
|
51
|
-
{
|
52
|
-
insert: [Activity::Adds::Insert.method(:Append)], # append to the very end of tW.
|
53
|
-
row: Activity::TaskWrap::Pipeline.Row("task_wrap.capture_return", Trace.method(:capture_return))
|
54
|
-
},
|
40
|
+
def task_wrap_extensions
|
41
|
+
Trailblazer::Activity::TaskWrap.Extension(
|
42
|
+
[Trace.method(:capture_args), id: "task_wrap.capture_args", prepend: "task_wrap.call_task"],
|
43
|
+
[Trace.method(:capture_return), id: "task_wrap.capture_return", append: nil], # append to the very end of tW.
|
55
44
|
)
|
56
45
|
end
|
57
46
|
|
@@ -60,112 +49,62 @@ module Trailblazer::Developer
|
|
60
49
|
# us a better way.
|
61
50
|
# taskWrap step to capture incoming arguments of a step.
|
62
51
|
def capture_args(wrap_config, ((ctx, flow), circuit_options))
|
63
|
-
flow
|
52
|
+
original_args = [[ctx, flow], circuit_options]
|
64
53
|
|
65
|
-
flow[:
|
66
|
-
|
67
|
-
|
68
|
-
flow[:input_data_collector].call(wrap_config, [ctx, flow], circuit_options)
|
69
|
-
).freeze
|
54
|
+
captured_input = Captured(Captured::Input, flow[:input_data_collector], wrap_config, original_args)
|
55
|
+
|
56
|
+
flow[:stack] << captured_input
|
70
57
|
|
71
|
-
return wrap_config,
|
58
|
+
return wrap_config, original_args
|
72
59
|
end
|
73
60
|
|
74
61
|
# taskWrap step to capture outgoing arguments from a step.
|
75
62
|
def capture_return(wrap_config, ((ctx, flow), circuit_options))
|
76
|
-
flow
|
77
|
-
wrap_config[:task],
|
78
|
-
{},
|
79
|
-
flow[:output_data_collector].call(wrap_config, [ctx, flow], circuit_options)
|
80
|
-
).freeze
|
63
|
+
original_args = [[ctx, flow], circuit_options]
|
81
64
|
|
82
|
-
flow[:
|
65
|
+
captured_output = Captured(Captured::Output, flow[:output_data_collector], wrap_config, original_args)
|
83
66
|
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
def default_input_data_collector(wrap_config, (ctx, _), circuit_options)
|
88
|
-
graph = Trailblazer::Activity::Introspect::Graph(circuit_options[:activity])
|
89
|
-
task = wrap_config[:task]
|
90
|
-
name = (node = graph.find { |node| node[:task] == task }) ? node[:id] : task
|
91
|
-
|
92
|
-
{ ctx: ctx, task_name: name }
|
93
|
-
end
|
67
|
+
flow[:stack] << captured_output
|
94
68
|
|
95
|
-
|
96
|
-
{ ctx: ctx, signal: wrap_config[:return_signal] }
|
69
|
+
return wrap_config, original_args
|
97
70
|
end
|
98
71
|
|
99
|
-
|
100
|
-
|
101
|
-
#
|
102
|
-
# Level[
|
103
|
-
# Level[ ==> this is a scalar task
|
104
|
-
# Entity::Input
|
105
|
-
# Entity::Output
|
106
|
-
# ]
|
107
|
-
# Level[ ==> nested task
|
108
|
-
# Entity::Input
|
109
|
-
# Level[
|
110
|
-
# Entity::Input
|
111
|
-
# Entity::Output
|
112
|
-
# ]
|
113
|
-
# Entity::Output
|
114
|
-
# ]
|
115
|
-
# ]
|
116
|
-
Entity = Struct.new(:task, :activity, :data)
|
117
|
-
Entity::Input = Class.new(Entity)
|
118
|
-
Entity::Output = Class.new(Entity)
|
119
|
-
|
120
|
-
class Level < Array
|
121
|
-
def inspect
|
122
|
-
%{<Level>#{super}}
|
123
|
-
end
|
124
|
-
|
125
|
-
# @param level {Trace::Level}
|
126
|
-
def self.input_output_nested_for_level(level)
|
127
|
-
input = level[0]
|
128
|
-
output = level[-1]
|
129
|
-
|
130
|
-
output, nested = output.is_a?(Entity::Output) ? [output, level-[input, output]] : [nil, level[1..-1]]
|
72
|
+
def Captured(captured_class, data_collector, wrap_config, ((ctx, flow), circuit_options))
|
73
|
+
collected_data = data_collector.call(wrap_config, [[ctx, flow], circuit_options])
|
131
74
|
|
132
|
-
|
133
|
-
|
75
|
+
captured_class.new( # either Input or Output
|
76
|
+
wrap_config[:task],
|
77
|
+
circuit_options[:activity],
|
78
|
+
collected_data
|
79
|
+
).freeze
|
134
80
|
end
|
135
81
|
|
136
|
-
#
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
@nested = Level.new
|
142
|
-
@stack = [ @nested ]
|
143
|
-
end
|
144
|
-
|
145
|
-
def indent!
|
146
|
-
current << indented = Level.new
|
147
|
-
@stack << indented
|
148
|
-
end
|
149
|
-
|
150
|
-
def unindent!
|
151
|
-
@stack.pop
|
152
|
-
end
|
153
|
-
|
154
|
-
def <<(entity)
|
155
|
-
@top = entity
|
82
|
+
# Called in {#Captured}.
|
83
|
+
# DISCUSS: this is where to start for a new {Inspector} implementation.
|
84
|
+
def default_input_data_collector(wrap_config, ((ctx, _), _)) # DISCUSS: would it be faster to access ctx via {original_args[0][0]}?
|
85
|
+
# mutable, old_ctx = ctx.decompose
|
86
|
+
# mutable, old_ctx = ctx, nil
|
156
87
|
|
157
|
-
|
158
|
-
|
88
|
+
{
|
89
|
+
# ctx: ctx.to_h.freeze,
|
90
|
+
ctx_snapshot: ctx.to_h.collect { |k,v| [k, v.inspect] }.to_h,
|
91
|
+
} # TODO: proper snapshot!
|
92
|
+
end
|
159
93
|
|
160
|
-
|
161
|
-
|
162
|
-
|
94
|
+
# Called in {#Captured}.
|
95
|
+
def default_output_data_collector(wrap_config, ((ctx, _), _))
|
96
|
+
returned_ctx, _ = wrap_config[:return_args]
|
163
97
|
|
164
|
-
|
98
|
+
# FIXME: snapshot!
|
99
|
+
{
|
100
|
+
# ctx: ctx.to_h.freeze,
|
101
|
+
ctx_snapshot: returned_ctx.to_h.collect { |k,v| [k, v.inspect] }.to_h,
|
102
|
+
signal: wrap_config[:return_signal]
|
103
|
+
}
|
104
|
+
end
|
165
105
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
end # Stack
|
106
|
+
Captured = Struct.new(:task, :activity, :data)
|
107
|
+
Captured::Input = Class.new(Captured)
|
108
|
+
Captured::Output = Class.new(Captured)
|
170
109
|
end
|
171
110
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module Trailblazer::Developer
|
3
2
|
module Wtf
|
4
3
|
|
@@ -15,24 +14,24 @@ module Trailblazer::Developer
|
|
15
14
|
|
16
15
|
module_function
|
17
16
|
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
[task_node.level, value]
|
17
|
+
# {options} can be {style: {#<Captured::Input> => [:red, :bold]}}
|
18
|
+
def call(tree:, debugger_node:, style: {}, **options)
|
19
|
+
label = styled_label(tree, debugger_node, style: style, **options)
|
20
|
+
|
21
|
+
[debugger_node.level, label]
|
24
22
|
end
|
25
23
|
|
26
|
-
def
|
27
|
-
|
28
|
-
return %{#{fmt(fmt(task_node.value, :red), :bold)}}
|
29
|
-
end
|
24
|
+
def styled_label(tree, debugger_node, color_map:, **options)
|
25
|
+
label = apply_style(debugger_node.label, debugger_node, **options)
|
30
26
|
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
%{#{fmt(label, color_map[ signal_of(debugger_node) ])}}
|
28
|
+
end
|
29
|
+
|
30
|
+
def apply_style(label, debugger_node, style:, **)
|
31
|
+
return label unless styles = style[debugger_node.captured_input]
|
34
32
|
|
35
|
-
|
33
|
+
styles.each { |s| label = fmt(label, s) }
|
34
|
+
label
|
36
35
|
end
|
37
36
|
|
38
37
|
def fmt(line, style)
|
@@ -44,7 +43,7 @@ module Trailblazer::Developer
|
|
44
43
|
end
|
45
44
|
|
46
45
|
def signal_of(task_node)
|
47
|
-
entity_signal = task_node.
|
46
|
+
entity_signal = task_node.captured_output.data[:signal]
|
48
47
|
entity_klass = entity_signal.is_a?(Class) ? entity_signal : entity_signal.class
|
49
48
|
|
50
49
|
SIGNALS_MAP[entity_klass.name.to_sym]
|
@@ -14,77 +14,64 @@ module Trailblazer::Developer
|
|
14
14
|
|
15
15
|
# Run {activity} with tracing enabled and inject a mutable {Stack} instance.
|
16
16
|
# This allows to display the trace even when an exception happened
|
17
|
-
def invoke(activity, (ctx, flow_options), **circuit_options)
|
18
|
-
|
19
|
-
activity, [ctx, flow_options], **circuit_options
|
20
|
-
)
|
17
|
+
def invoke(activity, (ctx, flow_options), present_options: {}, **circuit_options)
|
18
|
+
flow_options ||= {}
|
21
19
|
|
22
|
-
|
23
|
-
activity, [ctx, flow_options], **circuit_options
|
24
|
-
)
|
20
|
+
stack = Trace::Stack.new # unfortunately, we need this mutable object before things break.
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
renderer: Wtf::Renderer,
|
31
|
-
color_map: Wtf::Renderer::DEFAULT_COLOR_MAP.merge( flow_options[:color_map] || {} ),
|
22
|
+
complete_stack, signal, (ctx, flow_options) = Trace.invoke(
|
23
|
+
activity,
|
24
|
+
[ctx, flow_options.merge(stack: stack)],
|
25
|
+
**circuit_options
|
32
26
|
)
|
33
|
-
end
|
34
|
-
|
35
|
-
def arguments_for_trace(activity, (ctx, original_flow_options), **circuit_options)
|
36
|
-
default_flow_options = {
|
37
|
-
# this instance gets mutated with every step. unfortunately, there is
|
38
|
-
# no other way in Ruby to keep the trace even when an exception was thrown.
|
39
|
-
stack: Trace::Stack.new,
|
40
|
-
|
41
|
-
input_data_collector: method(:trace_input_data_collector),
|
42
|
-
output_data_collector: method(:trace_output_data_collector),
|
43
|
-
}
|
44
27
|
|
45
|
-
|
46
|
-
flow_options = { **default_flow_options, **Hash( original_flow_options ) }
|
47
|
-
|
48
|
-
# Normalize `focus_on` param to
|
49
|
-
# 1. Wrap step and variable names into an array if not already
|
50
|
-
flow_options[:focus_on] = {
|
51
|
-
steps: Array( flow_options.dig(:focus_on, :steps) ),
|
52
|
-
variables: Array( flow_options.dig(:focus_on, :variables) ),
|
53
|
-
}
|
28
|
+
return signal, [ctx, flow_options], circuit_options
|
54
29
|
|
55
|
-
|
56
|
-
|
30
|
+
ensure
|
31
|
+
# incomplete_stack = flow_options[:stack]
|
32
|
+
incomplete_stack = stack
|
57
33
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
def trace_input_data_collector(wrap_config, (ctx, flow_options), circuit_options)
|
62
|
-
data = Trace.default_input_data_collector(wrap_config, [ctx, flow_options], circuit_options)
|
34
|
+
# in 99%, exception_source is a {Captured::Input}.
|
35
|
+
exception_source = incomplete_stack.to_a.last # DISCUSS: in most cases, this is where the problem has happened.
|
36
|
+
# However, what if an error happens in, say, an input filter? TODO: test this
|
63
37
|
|
64
|
-
|
65
|
-
data[:focused_variables] = Trace::Focusable.capture_variables_from(ctx, **flow_options)
|
66
|
-
end
|
38
|
+
complete_stack = Exception::Stack.complete(incomplete_stack) # TODO: only in case of exception!
|
67
39
|
|
68
|
-
|
40
|
+
puts Trace::Present.(
|
41
|
+
complete_stack,
|
42
|
+
# we can hand in options per node, identified by their captured_input part.
|
43
|
+
node_options: {
|
44
|
+
exception_source => {data: {exception_source: true}}, # goes to {Debugger::Node.build}
|
45
|
+
},
|
46
|
+
|
47
|
+
renderer: Wtf::Renderer,
|
48
|
+
color_map: Wtf::Renderer::DEFAULT_COLOR_MAP.merge( flow_options[:color_map] || {} ),
|
49
|
+
style: {exception_source => [:red, :bold]},
|
50
|
+
**present_options, # TODO: test.
|
51
|
+
)
|
69
52
|
end
|
70
53
|
|
71
|
-
|
72
|
-
|
73
|
-
|
54
|
+
module Exception
|
55
|
+
# When an exception occurs the Stack instance is incomplete - it is missing Captured::Output instances
|
56
|
+
# for Inputs still open. This method adds the missing elements so the Trace::Tree algorithm doesn't crash.
|
57
|
+
module Stack
|
58
|
+
def self.complete(incomplete_stack)
|
59
|
+
processed = []
|
74
60
|
|
75
|
-
|
76
|
-
|
77
|
-
|
61
|
+
incomplete_stack.to_a.each do |captured|
|
62
|
+
if captured.is_a?(Trace::Captured::Input)
|
63
|
+
processed << captured
|
64
|
+
else
|
65
|
+
processed.pop
|
66
|
+
end
|
67
|
+
end
|
78
68
|
|
79
|
-
|
80
|
-
end
|
69
|
+
missing_captured = processed.reverse.collect { |captured| Trace::Captured::Output.new(captured.task, captured.activity, {}) }
|
81
70
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
return true if focus_on[:steps].empty? && focus_on[:variables].any? # For selected vars but all steps
|
71
|
+
Trace::Stack.new(incomplete_stack.to_a + missing_captured)
|
72
|
+
end
|
73
|
+
end # Stack
|
86
74
|
|
87
|
-
false
|
88
75
|
end
|
89
76
|
end
|
90
77
|
end
|
@@ -6,11 +6,17 @@ module Trailblazer
|
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
+
require "trailblazer/activity"
|
9
10
|
require "trailblazer/developer/wtf"
|
10
11
|
require "trailblazer/developer/wtf/renderer"
|
11
12
|
require "trailblazer/developer/trace"
|
13
|
+
require "trailblazer/developer/trace/stack"
|
14
|
+
require "trailblazer/developer/trace/tree"
|
12
15
|
require "trailblazer/developer/trace/present"
|
13
|
-
require "trailblazer/developer/trace/
|
14
|
-
require "trailblazer/developer/trace/inspector"
|
16
|
+
require "trailblazer/developer/trace/debugger"
|
15
17
|
require "trailblazer/developer/render/circuit"
|
16
18
|
require "trailblazer/developer/render/linear"
|
19
|
+
require "trailblazer/developer/render/task_wrap"
|
20
|
+
require "trailblazer/developer/introspect" # TODO: might get removed, again.
|
21
|
+
require "trailblazer/developer/trace/debugger/normalizer"
|
22
|
+
require "trailblazer/developer/introspect/graph"
|
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
|
11
11
|
spec.summary = "Developer tools for Trailblazer."
|
12
12
|
spec.description = "Developer tools for Trailblazer: debugger, activity visualizer and tracing."
|
13
|
-
spec.homepage = "http://trailblazer.to"
|
13
|
+
spec.homepage = "http://trailblazer.to/2.1/docs/trailblazer.html#trailblazer-developer"
|
14
14
|
spec.license = "LGPL-3.0"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
@@ -22,7 +22,8 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency "minitest"
|
23
23
|
spec.add_development_dependency "minitest-line"
|
24
24
|
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "trailblazer-operation", ">= 0.10.0"
|
25
26
|
|
26
|
-
spec.add_dependency "trailblazer-activity-dsl-linear", ">= 1.
|
27
|
+
spec.add_dependency "trailblazer-activity-dsl-linear", ">= 1.2.0", "< 1.3.0"
|
27
28
|
spec.add_dependency "hirb"
|
28
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trailblazer-developer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,26 +66,40 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: trailblazer-operation
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.10.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.10.0
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: trailblazer-activity-dsl-linear
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
87
|
- - ">="
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: 1.
|
89
|
+
version: 1.2.0
|
76
90
|
- - "<"
|
77
91
|
- !ruby/object:Gem::Version
|
78
|
-
version: 1.
|
92
|
+
version: 1.3.0
|
79
93
|
type: :runtime
|
80
94
|
prerelease: false
|
81
95
|
version_requirements: !ruby/object:Gem::Requirement
|
82
96
|
requirements:
|
83
97
|
- - ">="
|
84
98
|
- !ruby/object:Gem::Version
|
85
|
-
version: 1.
|
99
|
+
version: 1.2.0
|
86
100
|
- - "<"
|
87
101
|
- !ruby/object:Gem::Version
|
88
|
-
version: 1.
|
102
|
+
version: 1.3.0
|
89
103
|
- !ruby/object:Gem::Dependency
|
90
104
|
name: hirb
|
91
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,19 +130,23 @@ files:
|
|
116
130
|
- Rakefile
|
117
131
|
- bin/console
|
118
132
|
- bin/setup
|
119
|
-
- gems.local.rb
|
120
133
|
- lib/trailblazer/developer.rb
|
134
|
+
- lib/trailblazer/developer/introspect.rb
|
135
|
+
- lib/trailblazer/developer/introspect/graph.rb
|
121
136
|
- lib/trailblazer/developer/render/circuit.rb
|
122
137
|
- lib/trailblazer/developer/render/linear.rb
|
138
|
+
- lib/trailblazer/developer/render/task_wrap.rb
|
123
139
|
- lib/trailblazer/developer/trace.rb
|
124
|
-
- lib/trailblazer/developer/trace/
|
125
|
-
- lib/trailblazer/developer/trace/
|
140
|
+
- lib/trailblazer/developer/trace/debugger.rb
|
141
|
+
- lib/trailblazer/developer/trace/debugger/normalizer.rb
|
126
142
|
- lib/trailblazer/developer/trace/present.rb
|
143
|
+
- lib/trailblazer/developer/trace/stack.rb
|
144
|
+
- lib/trailblazer/developer/trace/tree.rb
|
127
145
|
- lib/trailblazer/developer/version.rb
|
128
146
|
- lib/trailblazer/developer/wtf.rb
|
129
147
|
- lib/trailblazer/developer/wtf/renderer.rb
|
130
148
|
- trailblazer-developer.gemspec
|
131
|
-
homepage: http://trailblazer.to
|
149
|
+
homepage: http://trailblazer.to/2.1/docs/trailblazer.html#trailblazer-developer
|
132
150
|
licenses:
|
133
151
|
- LGPL-3.0
|
134
152
|
metadata: {}
|
data/gems.local.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
source "https://rubygems.org"
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in trailblazer-developer.gemspec
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
gem "trailblazer-activity", path: "../trailblazer-activity"
|
7
|
-
gem "trailblazer-activity-dsl-linear", path: "../trailblazer-activity-dsl-linear"
|
8
|
-
gem "representable"
|
9
|
-
gem 'pry-byebug'
|
10
|
-
gem "faraday"
|
11
|
-
gem "multi_json"
|
@@ -1,78 +0,0 @@
|
|
1
|
-
module Trailblazer
|
2
|
-
module Developer
|
3
|
-
module Trace
|
4
|
-
|
5
|
-
module Focusable
|
6
|
-
module_function
|
7
|
-
|
8
|
-
# Get inspect of {focus_on.variables} or current {ctx}
|
9
|
-
def capture_variables_from(ctx, focus_on:, inspector: Trace::Inspector, **flow_options)
|
10
|
-
# ctx keys to be captured, for example [:current_user, :model, ....]
|
11
|
-
variables = (selected = focus_on[:variables]).any? ? selected : ctx.keys
|
12
|
-
|
13
|
-
variables.each_with_object({}) do |variable, result|
|
14
|
-
if variable.is_a?(Proc) # To allow deep key access from ctx
|
15
|
-
result[:Custom] = inspector.(variable.call(ctx), **flow_options)
|
16
|
-
else
|
17
|
-
result[variable] = inspector.(ctx[variable], **flow_options)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Generate Hirb's vertical table nodes from captured ctx of each step
|
23
|
-
# |-- some step name
|
24
|
-
# | |-- ********** Input **********
|
25
|
-
# message: "WTF!"
|
26
|
-
# seq: []
|
27
|
-
# | `-- ********** Output **********
|
28
|
-
# message: "WTF!"
|
29
|
-
# seq: [:a]
|
30
|
-
def tree_nodes_for(level, input:, output:, **options)
|
31
|
-
# TODO: Reverting `Hash#compact` usage as it is not supported in Ruby <= 2.4
|
32
|
-
# Once the support is droped, revert actual code with below and remove entity check.
|
33
|
-
# input_output_nodes = { Input: input, Output: output }.compact.collect do |table_header, entity|
|
34
|
-
|
35
|
-
input_output_nodes = { Input: input, Output: output }.collect do |table_header, entity|
|
36
|
-
next unless entity
|
37
|
-
next unless Array( entity.data[:focused_variables] ).any?
|
38
|
-
|
39
|
-
table = vertical_table_for(entity.data[:focused_variables], table_header: table_header)
|
40
|
-
Present::TreeNodes::Node.new(level + 1, table, input, output, options).freeze
|
41
|
-
end
|
42
|
-
|
43
|
-
input_output_nodes.compact
|
44
|
-
end
|
45
|
-
|
46
|
-
# @private
|
47
|
-
def vertical_table_for(focused_variables, table_header:)
|
48
|
-
patched_vertical_table.render(
|
49
|
-
Array[ focused_variables ],
|
50
|
-
description: nil,
|
51
|
-
table_header: table_header, # Custom option, not from Hirb
|
52
|
-
)
|
53
|
-
end
|
54
|
-
|
55
|
-
# Overrding `Hirb::Helpers::VerticalTable#render_rows` because there is no option
|
56
|
-
# to customize vertical table's row header :(
|
57
|
-
# We need it to print if given entity is Input/Output
|
58
|
-
#
|
59
|
-
# @private
|
60
|
-
def patched_vertical_table
|
61
|
-
table = Class.new(Hirb::Helpers::VerticalTable)
|
62
|
-
|
63
|
-
table.send(:define_method, :render_rows) do
|
64
|
-
longest_header = Hirb::String.size (@headers.values.sort_by {|e| Hirb::String.size(e) }.last || '')
|
65
|
-
stars = "*" * [(longest_header + (longest_header / 2)), 3].max
|
66
|
-
|
67
|
-
@rows.map do |row|
|
68
|
-
"#{stars} #{@options[:table_header]} #{stars}\n" +
|
69
|
-
@fields.map{ |f| "#{Hirb::String.rjust(@headers[f], longest_header)}: #{row[f]}" }.join("\n")
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
table
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|