trailblazer-developer 0.0.10 → 0.0.15

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: e6a577980533d74f29b616b2b5d3d85026a8d7ca20f096a9d9af463e30994fe3
4
- data.tar.gz: '03894756cc87b350bd9d0c71ee7c22cc951e7302869e20a95c8facd21d585c84'
3
+ metadata.gz: d011963349460317f1cbf1face4be2bc4b7d4b785d16c407f6ae406ee45d2896
4
+ data.tar.gz: c98a3a9b80e834636b72f4c28b49f8b98f43fc72cde7763716163d58414cba1b
5
5
  SHA512:
6
- metadata.gz: b03caa6b40f5e45acc588999dc43b891b9f0f4d9ced50261acbe3919c1d89d4feb24c7ba9a4dd7924b10f72b87fb32d775d8a1ed000d8a6dea33da02b15fd5b6
7
- data.tar.gz: 6a8aa191f8132ffb968cdf0256985a4bbc5ea916a6240d94baac3a50a621e8b9a0b8e38aec84cf4ba336f32cecdafa5c31bd1a271da2074ce32c64d09e778e72
6
+ metadata.gz: 100d9a06f9d5f1b4e142a55831ca55aaaeb4bfd8c7a2b8fa81101549764841d25306999dfec32641044d6d11c8d47f1f3e53d60a2b0fd5f1800a3cb653185b91
7
+ data.tar.gz: d5ca2e3657f4a79acac4df4f51bd1b291f736d126a56a4b22667083c2acff7dac4751679cabfd0542dde25290cc74befcd1c197ab8811e76d793e84d57947210
@@ -1,7 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.6.2
4
- - 2.5.5
5
- - 2.4.4
3
+ - 2.6
4
+ - 2.5
5
+ - 2.4
6
6
 
7
7
  cache: bundler
data/README.md CHANGED
@@ -4,7 +4,7 @@ _Developer tools for Trailblazers._
4
4
 
5
5
  ## Documentation
6
6
 
7
- Find the complete documentation on the project website: [http://trb.to/2.1#developer]
7
+ Find the complete documentation on the project website: [http://2019.trailblazer.to/2.1/docs/developer.html]
8
8
 
9
9
  ## Summary
10
10
 
data/Rakefile CHANGED
@@ -1,6 +1,5 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
- require "rubocop/rake_task"
4
3
 
5
4
  Rake::TestTask.new(:test) do |t|
6
5
  t.libs << "test"
@@ -8,7 +7,5 @@ Rake::TestTask.new(:test) do |t|
8
7
  t.test_files = FileList["test/**/*_test.rb"]
9
8
  end
10
9
 
11
- RuboCop::RakeTask.new(:rubocop)
12
-
13
10
  desc "Running Tests"
14
11
  task default: %i[test]
@@ -7,8 +7,11 @@ module Trailblazer
7
7
  end
8
8
 
9
9
  require "trailblazer/developer/wtf"
10
+ require "trailblazer/developer/wtf/renderer"
10
11
  require "trailblazer/developer/trace"
11
12
  require "trailblazer/developer/trace/present"
13
+ require "trailblazer/developer/trace/focusable"
14
+ require "trailblazer/developer/trace/inspector"
12
15
  require "trailblazer/developer/generate"
13
16
  require "trailblazer/developer/render/circuit"
14
17
  require "trailblazer/developer/render/linear"
@@ -1,3 +1,26 @@
1
+ # 0.0.15
2
+
3
+ * Fix `Dev.wtf` circuit interface definition
4
+
5
+ # 0.0.14
6
+
7
+ * Revert declarative warning changes
8
+
9
+ # 0.0.13
10
+
11
+ * Allow focusing on selected variables for all steps in wtf
12
+ * Fix declarative deprecation warning
13
+
14
+ # 0.0.12
15
+
16
+ * Revert Hash#compact usage to support Rubies <= 2.4
17
+
18
+ # 0.0.11
19
+
20
+ * Allow injecting custom data collector in Trace API, to collect custom input/output ctx of task nodes.
21
+ * Allow focusing on specfic steps and ctx variables in Dev.wtf?
22
+ * Allow custom inspection while tracing using Inspector definations
23
+
1
24
  # 0.0.10
2
25
 
3
26
  * Make Generate::Pipeline an activity for better customization/extendability.
@@ -31,7 +31,7 @@ module Trailblazer::Developer
31
31
  return false unless response.status == 200
32
32
 
33
33
  # token = CGI::Cookie.parse(response.headers["set-cookie"])["token"][0]
34
- token = JSON.parse(response.body)["token"]
34
+ JSON.parse(response.body)["token"]
35
35
  end
36
36
 
37
37
  def export_diagram(id:, query:, **options)
@@ -60,7 +60,7 @@ module Trailblazer::Developer
60
60
  def request(host:, url:, method:, token:, body:, **)
61
61
  conn = Faraday.new(url: host)
62
62
 
63
- response = conn.send(method) do |req|
63
+ conn.send(method) do |req|
64
64
  req.url url
65
65
  req.headers["Content-Type"] = "application/json"
66
66
  req.body = body
@@ -31,7 +31,7 @@ module Trailblazer
31
31
  end
32
32
 
33
33
  def call(hash)
34
- signal, (ctx, _) = Activity::TaskWrap.invoke(Pipeline, hash: hash)
34
+ _, (ctx, _) = Activity::TaskWrap.invoke(Pipeline, hash: hash)
35
35
  ctx[:intermediate]
36
36
  end
37
37
 
@@ -51,16 +51,16 @@ module Trailblazer
51
51
  wiring = elements.collect { |el|
52
52
  data = data_for(el)
53
53
 
54
- [inter.TaskRef(el.id, data), el.linksTo.collect { |arrow| inter.Out(semantic_for(arrow.to_h), arrow.target) } ] }
54
+ [inter.TaskRef(el.id, data), el.linksTo.collect { |arrow| inter.Out(semantic_for(**arrow.to_h), arrow.target) } ] }
55
55
  wiring = Hash[wiring]
56
56
 
57
57
  # end events need this stupid special handling
58
58
  # DISCUSS: currently, the END-SEMANTIC is read from the event's label.
59
59
  wiring = wiring.merge(Hash[
60
60
  end_events.collect do |_end|
61
- ref, outputs = wiring.find { |ref, _| ref.id == _end.id }
61
+ ref, = wiring.find { |ref, _| ref.id == _end.id }
62
62
 
63
- [ref, [inter.Out(semantic_for(_end.to_h)|| raise, nil)]] # TODO: test the raise, happens when the semantic of an End can't be distinguished. # TODO: don't extract semantic from :label but from :data.
63
+ [ref, [inter.Out(semantic_for(**_end.to_h)|| raise, nil)]] # TODO: test the raise, happens when the semantic of an End can't be distinguished. # TODO: don't extract semantic from :label but from :data.
64
64
  end
65
65
  ])
66
66
  # pp wiring
@@ -7,26 +7,33 @@ module Trailblazer::Developer
7
7
 
8
8
  class << self
9
9
  # Public entry point to activate tracing when running {activity}.
10
- def call(activity, (ctx, flow_options), circuit_options={})
11
- activity, (ctx, flow_options), circuit_options = Trace.arguments_for_call( activity, [ctx, flow_options], circuit_options ) # only run once for the entire circuit!
10
+ def call(activity, (ctx, flow_options), **circuit_options)
11
+ activity, (ctx, flow_options), circuit_options = Trace.arguments_for_call( activity, [ctx, flow_options], **circuit_options ) # only run once for the entire circuit!
12
12
 
13
- signal, (ctx, flow_options) = Activity::TaskWrap.invoke(activity, [ctx, flow_options], circuit_options)
13
+ signal, (ctx, flow_options) = Activity::TaskWrap.invoke(activity, [ctx, flow_options], **circuit_options)
14
14
 
15
15
  return flow_options[:stack], signal, [ctx, flow_options]
16
16
  end
17
17
 
18
18
  alias_method :invoke, :call
19
19
 
20
- def arguments_for_call(activity, (options, flow_options), **circuit_options)
21
- tracing_flow_options = {
20
+ def arguments_for_call(activity, (options, original_flow_options), **original_circuit_options)
21
+ default_flow_options = {
22
22
  stack: Trace::Stack.new,
23
+
24
+ input_data_collector: Trace.method(:default_input_data_collector),
25
+ output_data_collector: Trace.method(:default_output_data_collector),
23
26
  }
24
27
 
25
- tracing_circuit_options = {
28
+ flow_options = { **default_flow_options, **Hash( original_flow_options ) }
29
+
30
+ default_circuit_options = {
26
31
  wrap_runtime: ::Hash.new(Trace.merge_plan), # DISCUSS: this overrides existing {:wrap_runtime}.
27
32
  }
28
33
 
29
- return activity, [ options, tracing_flow_options.merge(flow_options) ], circuit_options.merge(tracing_circuit_options)
34
+ circuit_options = { **original_circuit_options, **default_circuit_options }
35
+
36
+ return activity, [ options, flow_options ], circuit_options
30
37
  end
31
38
  end
32
39
 
@@ -42,38 +49,45 @@ module Trailblazer::Developer
42
49
  )
43
50
  end
44
51
 
52
+ # It's important to understand that {flow[:stack]} is mutated by design. This is needed so
53
+ # in case of exceptions we still have a "global" trace - unfortunately Ruby doesn't allow
54
+ # us a better way.
45
55
  # taskWrap step to capture incoming arguments of a step.
46
- def capture_args(wrap_config, original_args)
47
- original_args = capture_for(wrap_config[:task], *original_args)
56
+ def capture_args(wrap_config, ((ctx, flow), circuit_options))
57
+ flow[:stack].indent!
48
58
 
49
- return wrap_config, original_args
59
+ flow[:stack] << Entity::Input.new(
60
+ wrap_config[:task],
61
+ circuit_options[:activity],
62
+ flow[:input_data_collector].call(wrap_config, [ctx, flow], circuit_options)
63
+ ).freeze
64
+
65
+ return wrap_config, [[ctx, flow], circuit_options]
50
66
  end
51
67
 
52
68
  # taskWrap step to capture outgoing arguments from a step.
53
- def capture_return(wrap_config, original_args)
54
- (original_options, original_flow_options, _) = original_args[0]
55
-
56
- original_flow_options[:stack] << Entity::Output.new(
57
- wrap_config[:task], {}, wrap_config[:return_signal]
69
+ def capture_return(wrap_config, ((ctx, flow), circuit_options))
70
+ flow[:stack] << Entity::Output.new(
71
+ wrap_config[:task],
72
+ {},
73
+ flow[:output_data_collector].call(wrap_config, [ctx, flow], circuit_options)
58
74
  ).freeze
59
75
 
60
- original_flow_options[:stack].unindent!
76
+ flow[:stack].unindent!
61
77
 
62
-
63
- return wrap_config, original_args
78
+ return wrap_config, [[ctx, flow], circuit_options]
64
79
  end
65
80
 
66
- # It's important to understand that {flow[:stack]} is mutated by design. This is needed so
67
- # in case of exceptions we still have a "global" trace - unfortunately Ruby doesn't allow
68
- # us a better way.
69
- def capture_for(task, (ctx, flow), activity:, **circuit_options)
70
- flow[:stack].indent!
81
+ def default_input_data_collector(wrap_config, (ctx, _), circuit_options)
82
+ graph = Trailblazer::Activity::Introspect::Graph(circuit_options[:activity])
83
+ task = wrap_config[:task]
84
+ name = (node = graph.find { |node| node[:task] == task }) ? node[:id] : task
71
85
 
72
- flow[:stack] << Entity::Input.new(
73
- task, activity, [ctx, ctx.inspect]
74
- ).freeze
86
+ { ctx: ctx, task_name: name }
87
+ end
75
88
 
76
- return [ctx, flow], circuit_options.merge(activity: activity)
89
+ def default_output_data_collector(wrap_config, (ctx, _), _)
90
+ { ctx: ctx, signal: wrap_config[:return_signal] }
77
91
  end
78
92
 
79
93
  # Structures used in {capture_args} and {capture_return}.
@@ -115,6 +129,8 @@ module Trailblazer::Developer
115
129
 
116
130
  # Mutable/stateful per design. We want a (global) stack!
117
131
  class Stack
132
+ attr_reader :top
133
+
118
134
  def initialize
119
135
  @nested = Level.new
120
136
  @stack = [ @nested ]
@@ -129,8 +145,10 @@ module Trailblazer::Developer
129
145
  @stack.pop
130
146
  end
131
147
 
132
- def <<(args)
133
- current << args
148
+ def <<(entity)
149
+ @top = entity
150
+
151
+ current << entity
134
152
  end
135
153
 
136
154
  def to_a
@@ -0,0 +1,80 @@
1
+ require 'hirb'
2
+
3
+ module Trailblazer
4
+ module Developer
5
+ module Trace
6
+
7
+ module Focusable
8
+ module_function
9
+
10
+ # Get inspect of {focus_on.variables} or current {ctx}
11
+ def capture_variables_from(ctx, focus_on:, inspector: Trace::Inspector, **flow_options)
12
+ # ctx keys to be captured, for example [:current_user, :model, ....]
13
+ variables = (selected = focus_on[:variables]).any? ? selected : ctx.keys
14
+
15
+ variables.each_with_object({}) do |variable, result|
16
+ if variable.is_a?(Proc) # To allow deep key access from ctx
17
+ result[:Custom] = inspector.(variable.call(ctx), **flow_options)
18
+ else
19
+ result[variable] = inspector.(ctx[variable], **flow_options)
20
+ end
21
+ end
22
+ end
23
+
24
+ # Generate Hirb's vertical table nodes from captured ctx of each step
25
+ # |-- some step name
26
+ # | |-- ********** Input **********
27
+ # message: "WTF!"
28
+ # seq: []
29
+ # | `-- ********** Output **********
30
+ # message: "WTF!"
31
+ # seq: [:a]
32
+ def tree_nodes_for(level, input:, output:, **options)
33
+ # TODO: Reverting `Hash#compact` usage as it is not supported in Ruby <= 2.4
34
+ # Once the support is droped, revert actual code with below and remove entity check.
35
+ # input_output_nodes = { Input: input, Output: output }.compact.collect do |table_header, entity|
36
+
37
+ input_output_nodes = { Input: input, Output: output }.collect do |table_header, entity|
38
+ next unless entity
39
+ next unless Array( entity.data[:focused_variables] ).any?
40
+
41
+ table = vertical_table_for(entity.data[:focused_variables], table_header: table_header)
42
+ Present::TreeNodes::Node.new(level + 1, table, input, output, options).freeze
43
+ end
44
+
45
+ input_output_nodes.compact
46
+ end
47
+
48
+ # @private
49
+ def vertical_table_for(focused_variables, table_header:)
50
+ patched_vertical_table.render(
51
+ Array[ focused_variables ],
52
+ description: nil,
53
+ table_header: table_header, # Custom option, not from Hirb
54
+ )
55
+ end
56
+
57
+ # Overrding `Hirb::Helpers::VerticalTable#render_rows` because there is no option
58
+ # to customize vertical table's row header :(
59
+ # We need it to print if given entity is Input/Output
60
+ #
61
+ # @private
62
+ def patched_vertical_table
63
+ table = Class.new(Hirb::Helpers::VerticalTable)
64
+
65
+ table.send(:define_method, :render_rows) do
66
+ longest_header = Hirb::String.size (@headers.values.sort_by {|e| Hirb::String.size(e) }.last || '')
67
+ stars = "*" * [(longest_header + (longest_header / 2)), 3].max
68
+
69
+ @rows.map do |row|
70
+ "#{stars} #{@options[:table_header]} #{stars}\n" +
71
+ @fields.map{ |f| "#{Hirb::String.rjust(@headers[f], longest_header)}: #{row[f]}" }.join("\n")
72
+ end
73
+ end
74
+
75
+ table
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,48 @@
1
+ module Trailblazer
2
+ module Developer
3
+ module Trace
4
+
5
+ # This module does the inspection of given `ctx` with deep traversal.
6
+ # It only gets called when focusing is going on (i.e. focus_on API).
7
+ module Inspector
8
+ module_function
9
+
10
+ def call(value, default_inspector: method(:default_inspector), **)
11
+ return hash_inspector(value, default_inspector: default_inspector) if value.is_a?(Hash)
12
+ return array_inspector(value, default_inspector: default_inspector) if value.is_a?(Array)
13
+
14
+ default_inspector.(value)
15
+ end
16
+
17
+ def hash_inspector(value, default_inspector:)
18
+ Hash[
19
+ value.collect do |key, nested_value|
20
+ [key, call(nested_value, default_inspector: default_inspector)]
21
+ end
22
+ ]
23
+ end
24
+
25
+ def array_inspector(value, default_inspector:)
26
+ value.collect do |nested_value|
27
+ call(nested_value, default_inspector: default_inspector)
28
+ end
29
+ end
30
+
31
+ # To avoid additional query that AR::Relation#inspect makes,
32
+ # we're calling AR::Relation#to_sql to get plain SQL string instead.
33
+ def activerecord_relation_inspector(value)
34
+ { query: value.to_sql }
35
+ end
36
+
37
+ def default_inspector(value)
38
+ if defined?(ActiveRecord) && value.is_a?(ActiveRecord::Relation)
39
+ return activerecord_relation_inspector(value)
40
+ end
41
+
42
+ value.inspect
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -1,15 +1,12 @@
1
- require 'trailblazer/activity'
1
+ require 'hirb'
2
2
 
3
3
  module Trailblazer::Developer
4
4
  module Trace
5
5
  module Present
6
6
  module_function
7
7
 
8
- INDENTATION = " |".freeze
9
- STEP_PREFIX = "-- ".freeze
10
-
11
8
  def default_renderer(task_node:, **)
12
- [ task_node[:level], %{#{task_node[:name]}} ]
9
+ [ task_node.level, %{#{task_node.value}} ]
13
10
  end
14
11
 
15
12
  def call(stack, level: 1, tree: [], renderer: method(:default_renderer), **options)
@@ -17,43 +14,48 @@ module Trailblazer::Developer
17
14
  end
18
15
 
19
16
  def tree(stack, level, tree:, renderer:, **options)
20
- tree_for(stack, level, options.merge(tree: tree))
17
+ tree_for(stack, level, **options.merge(tree: tree))
21
18
 
22
19
  nodes = tree.each_with_index.map do |task_node, position|
23
20
  renderer.(task_node: task_node, position: position, tree: tree)
24
21
  end
25
22
 
26
- render_tree_for(nodes)
27
- end
28
-
29
- def render_tree_for(nodes)
30
- nodes.map { |level, node|
31
- indentation = INDENTATION * (level -1)
32
- indentation = indentation[0...-1] + "`" if level == 1 || /End./.match(node) # start or end step
33
- indentation + STEP_PREFIX + node
34
- }.join("\n")
23
+ Hirb::Console.format_output(nodes, class: :tree, type: :directory, multi_line_nodes: true)
35
24
  end
36
25
 
37
26
  def tree_for(stack, level, tree:, **options)
38
27
  stack.each do |lvl| # always a Stack::Task[input, ..., output]
39
28
  input, output, nested = Trace::Level.input_output_nested_for_level(lvl)
40
29
 
41
- task = input.task
42
-
43
- graph = Trailblazer::Activity::Introspect::Graph(input.activity)
44
-
45
- name = (node = graph.find { |node| node[:task] == task }) ? node[:id] : task
46
- name ||= task # FIXME: bullshit
47
-
48
- tree << { level: level, input: input, output: output, name: name, **options }
30
+ tree.push(*TreeNodes.for(level, options.merge(input: input, output: output)))
49
31
 
50
32
  if nested.any? # nesting
51
- tree_for(nested, level + 1, options.merge(tree: tree))
33
+ tree_for(nested, level + 1, **options.merge(tree: tree))
52
34
  end
53
35
 
54
36
  tree
55
37
  end
56
38
  end
39
+
40
+ module TreeNodes
41
+ Node = Struct.new(:level, :value, :input, :output, :options) do
42
+ # Allow access to any custom key from options, eg. color_map
43
+ def method_missing(name, *)
44
+ options[name]
45
+ end
46
+ end
47
+
48
+ module_function
49
+
50
+ def for(level, input:, output:, **options)
51
+ nodes = Array[ Node.new(level, input.data[:task_name], input, output, options).freeze ]
52
+
53
+ focused_nodes = Trace::Focusable.tree_nodes_for(level, input: input, output: output, **options)
54
+ nodes += focused_nodes if focused_nodes.length > 0
55
+
56
+ nodes
57
+ end
58
+ end
57
59
  end
58
60
  end
59
61
  end
@@ -1,7 +1,7 @@
1
1
  module Trailblazer
2
2
  module Version
3
3
  module Developer
4
- VERSION = "0.0.10"
4
+ VERSION = "0.0.15"
5
5
  end
6
6
  end
7
7
  end
@@ -12,95 +12,78 @@ module Trailblazer::Developer
12
12
  module Wtf
13
13
  module_function
14
14
 
15
- COLOR_MAP = { pass: :green, fail: :brown }
16
-
17
- SIGNALS_MAP = {
18
- 'Trailblazer::Activity::Right': :pass,
19
- 'Trailblazer::Activity::FastTrack::PassFast': :pass,
20
-
21
- 'Trailblazer::Activity::Left': :fail,
22
- 'Trailblazer::Activity::FastTrack::FailFast': :fail,
23
- }
24
-
25
15
  # Run {activity} with tracing enabled and inject a mutable {Stack} instance.
26
16
  # This allows to display the trace even when an exception happened
27
- def invoke(activity, (ctx, flow_options), *args)
28
- flow_options ||= {} # Ruby sucks.
29
-
30
- # this instance gets mutated with every step. unfortunately, there is
31
- # no other way in Ruby to keep the trace even when an exception was thrown.
32
- stack = Trace::Stack.new
33
-
34
- _returned_stack, *returned = Trace.invoke(
35
- activity,
36
- [
37
- ctx,
38
- flow_options.merge(stack: stack)
39
- ],
40
- *args
17
+ def invoke(activity, (ctx, flow_options), **circuit_options)
18
+ activity, (ctx, flow_options), circuit_options = Wtf.arguments_for_trace(
19
+ activity, [ctx, flow_options], circuit_options
41
20
  )
42
21
 
43
- returned
22
+ _returned_stack, signal, (ctx, flow_options) = Trace.invoke(
23
+ activity, [ctx, flow_options], circuit_options
24
+ )
25
+
26
+ return signal, [ctx, flow_options], circuit_options
44
27
  ensure
45
28
  puts Trace::Present.(
46
- stack,
47
- renderer: method(:renderer),
48
- color_map: COLOR_MAP.merge( flow_options[:color_map] || {} )
29
+ flow_options[:stack],
30
+ renderer: Wtf::Renderer,
31
+ color_map: Wtf::Renderer::DEFAULT_COLOR_MAP.merge( flow_options[:color_map] || {} ),
49
32
  )
50
33
  end
51
34
 
52
- def renderer(task_node:, position:, tree:)
53
- name, level, output, color_map = task_node.values_at(:name, :level, :output, :color_map)
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,
54
40
 
55
- if output.nil? && tree[position.next].nil? # i.e. when exception raised
56
- return [ level, %{#{fmt(fmt(name, :red), :bold)}} ]
57
- end
41
+ input_data_collector: method(:trace_input_data_collector),
42
+ output_data_collector: method(:trace_output_data_collector),
43
+ }
58
44
 
59
- if output.nil? # i.e. on entry/exit point of activity
60
- return [ level, %{#{name}} ]
61
- end
45
+ # Merge default options with flow_options as an order of precedence
46
+ flow_options = { **default_flow_options, **Hash( original_flow_options ) }
62
47
 
63
- [ level, %{#{fmt( name, color_map[ signal_of(output.data) ] )}} ]
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
+ }
54
+
55
+ return activity, [ ctx, flow_options ], circuit_options
64
56
  end
65
57
 
66
- def fmt(line, style)
67
- return line unless style
68
- String.send(style, line)
58
+ # Overring default input and output data collectors to collect/capture
59
+ # 1. inspect of focusable variables for given focusable step
60
+ # 2. Or inspect of focused variables for all steps
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)
63
+
64
+ if Wtf.caputure_variables?(step_name: data[:task_name], **flow_options)
65
+ data[:focused_variables] = Trace::Focusable.capture_variables_from(ctx, **flow_options)
66
+ end
67
+
68
+ data
69
69
  end
70
70
 
71
- def signal_of(entity_output)
72
- entity_klass = entity_output.is_a?(Class) ? entity_output : entity_output.class
73
- SIGNALS_MAP[entity_klass.name.to_sym]
71
+ def trace_output_data_collector(wrap_config, (ctx, flow_options), circuit_options)
72
+ data = Trace.default_output_data_collector(wrap_config, [ctx, flow_options], circuit_options)
73
+ input = flow_options[:stack].top
74
+
75
+ if Wtf.caputure_variables?(step_name: input.data[:task_name], **flow_options)
76
+ data[:focused_variables] = Trace::Focusable.capture_variables_from(ctx, **flow_options)
77
+ end
78
+
79
+ data
74
80
  end
75
81
 
76
- # Stolen from https://stackoverflow.com/questions/1489183/colorized-ruby-output
77
- #
78
- # TODO: this is just prototyping
79
- module String
80
- module_function
81
- def black(str); "\e[30m#{str}\e[0m" end
82
- def red(str); "\e[31m#{str}\e[0m" end
83
- def green(str); "\e[32m#{str}\e[0m" end
84
- def brown(str); "\e[33m#{str}\e[0m" end
85
- def blue(str); "\e[34m#{str}\e[0m" end
86
- def magenta(str); "\e[35m#{str}\e[0m" end
87
- def cyan(str); "\e[36m#{str}\e[0m" end
88
- def gray(str); "\e[37m#{str}\e[0m" end
89
-
90
- def bg_black(str); "\e[40m#{str}\e[0m" end
91
- def bg_red(str); "\e[41m#{str}\e[0m" end
92
- def bg_green(str); "\e[42m#{str}\e[0m" end
93
- def bg_brown(str); "\e[43m#{str}\e[0m" end
94
- def bg_blue(str); "\e[44m#{str}\e[0m" end
95
- def bg_magenta(str); "\e[45m#{str}\e[0m" end
96
- def bg_cyan(str); "\e[46m#{str}\e[0m" end
97
- def bg_gray(str); "\e[47m#{str}\e[0m" end
98
-
99
- def bold(str); "\e[1m#{str}\e[22m" end
100
- def italic(str); "\e[3m#{str}\e[23m" end
101
- def underline(str); "\e[4m#{str}\e[24m" end
102
- def blink(str); "\e[5m#{str}\e[25m" end
103
- def reverse_color(str); "\e[7m#{str}\e[27m" end
82
+ # private
83
+ def caputure_variables?(step_name:, focus_on:, **)
84
+ return true if focus_on[:steps].include?(step_name) # For given step
85
+ return true if focus_on[:steps].empty? && focus_on[:variables].any? # For selected vars but all steps
86
+ return false
104
87
  end
105
88
  end
106
89
  end
@@ -0,0 +1,78 @@
1
+ module Trailblazer::Developer
2
+ module Wtf
3
+
4
+ module Renderer
5
+ DEFAULT_COLOR_MAP = { pass: :green, fail: :brown }
6
+
7
+ SIGNALS_MAP = {
8
+ :'Trailblazer::Activity::Right' => :pass,
9
+ :'Trailblazer::Activity::FastTrack::PassFast' => :pass,
10
+
11
+ :'Trailblazer::Activity::Left' => :fail,
12
+ :'Trailblazer::Activity::FastTrack::FailFast' => :fail,
13
+ }
14
+
15
+ module_function
16
+
17
+ # tree: Array of Trace::TreeNodes::Node
18
+ # task_node - current Trace::TreeNodes::Node to render
19
+ # position - task_node's position in tree
20
+ def call(tree:, task_node:, position:)
21
+ value = value_for(tree, task_node, position)
22
+ [task_node.level, value]
23
+ end
24
+
25
+ def value_for(tree, task_node, position)
26
+ if task_node.output.nil? && tree[position.next].nil? # i.e. when exception raised
27
+ return %{#{fmt(fmt(task_node.value, :red), :bold)}}
28
+ end
29
+
30
+ if task_node.output.nil? # i.e. on entry/exit point of activity
31
+ return %{#{task_node.value}}
32
+ end
33
+
34
+ %{#{fmt(task_node.value, task_node.color_map[ signal_of(task_node) ])}}
35
+ end
36
+
37
+ def fmt(line, style)
38
+ return line unless style
39
+ String.send(style, line)
40
+ end
41
+
42
+ def signal_of(task_node)
43
+ entity_signal = task_node.output.data[:signal]
44
+ entity_klass = entity_signal.is_a?(Class) ? entity_signal : entity_signal.class
45
+
46
+ SIGNALS_MAP[entity_klass.name.to_sym]
47
+ end
48
+
49
+ # Stolen from https://stackoverflow.com/questions/1489183/colorized-ruby-output
50
+ #
51
+ # TODO: this is just prototyping
52
+ module String
53
+ module_function
54
+ def black(str); "\e[30m#{str}\e[0m" end
55
+ def red(str); "\e[31m#{str}\e[0m" end
56
+ def green(str); "\e[32m#{str}\e[0m" end
57
+ def brown(str); "\e[33m#{str}\e[0m" end
58
+ def blue(str); "\e[34m#{str}\e[0m" end
59
+ def magenta(str); "\e[35m#{str}\e[0m" end
60
+ def cyan(str); "\e[36m#{str}\e[0m" end
61
+ def gray(str); "\e[37m#{str}\e[0m" end
62
+
63
+ def bg_black(str); "\e[40m#{str}\e[0m" end
64
+ def bg_red(str); "\e[41m#{str}\e[0m" end
65
+ def bg_green(str); "\e[42m#{str}\e[0m" end
66
+ def bg_brown(str); "\e[43m#{str}\e[0m" end
67
+ def bg_blue(str); "\e[44m#{str}\e[0m" end
68
+ def bg_magenta(str); "\e[45m#{str}\e[0m" end
69
+ def bg_cyan(str); "\e[46m#{str}\e[0m" end
70
+ def bg_gray(str); "\e[47m#{str}\e[0m" end
71
+
72
+ def bold(str); "\e[1m#{str}\e[22m" end
73
+ def italic(str); "\e[3m#{str}\e[23m" end
74
+ def underline(str); "\e[4m#{str}\e[24m" end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -22,9 +22,9 @@ 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 "rubocop"
26
25
 
27
- spec.add_dependency "trailblazer-activity", ">= 0.10.0", "< 1.0.0"
26
+ spec.add_dependency "trailblazer-activity", ">= 0.11.0", "< 1.0.0"
28
27
  spec.add_dependency "trailblazer-activity-dsl-linear"
29
28
  spec.add_dependency "representable"
29
+ spec.add_dependency "hirb"
30
30
  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.10
4
+ version: 0.0.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-20 00:00:00.000000000 Z
11
+ date: 2020-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,41 +67,41 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rubocop
70
+ name: trailblazer-activity
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
75
+ version: 0.11.0
76
+ - - "<"
77
+ - !ruby/object:Gem::Version
78
+ version: 1.0.0
79
+ type: :runtime
77
80
  prerelease: false
78
81
  version_requirements: !ruby/object:Gem::Requirement
79
82
  requirements:
80
83
  - - ">="
81
84
  - !ruby/object:Gem::Version
82
- version: '0'
85
+ version: 0.11.0
86
+ - - "<"
87
+ - !ruby/object:Gem::Version
88
+ version: 1.0.0
83
89
  - !ruby/object:Gem::Dependency
84
- name: trailblazer-activity
90
+ name: trailblazer-activity-dsl-linear
85
91
  requirement: !ruby/object:Gem::Requirement
86
92
  requirements:
87
93
  - - ">="
88
94
  - !ruby/object:Gem::Version
89
- version: 0.10.0
90
- - - "<"
91
- - !ruby/object:Gem::Version
92
- version: 1.0.0
95
+ version: '0'
93
96
  type: :runtime
94
97
  prerelease: false
95
98
  version_requirements: !ruby/object:Gem::Requirement
96
99
  requirements:
97
100
  - - ">="
98
101
  - !ruby/object:Gem::Version
99
- version: 0.10.0
100
- - - "<"
101
- - !ruby/object:Gem::Version
102
- version: 1.0.0
102
+ version: '0'
103
103
  - !ruby/object:Gem::Dependency
104
- name: trailblazer-activity-dsl-linear
104
+ name: representable
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - ">="
@@ -115,7 +115,7 @@ dependencies:
115
115
  - !ruby/object:Gem::Version
116
116
  version: '0'
117
117
  - !ruby/object:Gem::Dependency
118
- name: representable
118
+ name: hirb
119
119
  requirement: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - ">="
@@ -136,7 +136,6 @@ extensions: []
136
136
  extra_rdoc_files: []
137
137
  files:
138
138
  - ".gitignore"
139
- - ".rubocop.yml"
140
139
  - ".travis.yml"
141
140
  - Gemfile
142
141
  - LICENSE
@@ -152,9 +151,12 @@ files:
152
151
  - lib/trailblazer/developer/render/circuit.rb
153
152
  - lib/trailblazer/developer/render/linear.rb
154
153
  - lib/trailblazer/developer/trace.rb
154
+ - lib/trailblazer/developer/trace/focusable.rb
155
+ - lib/trailblazer/developer/trace/inspector.rb
155
156
  - lib/trailblazer/developer/trace/present.rb
156
157
  - lib/trailblazer/developer/version.rb
157
158
  - lib/trailblazer/developer/wtf.rb
159
+ - lib/trailblazer/developer/wtf/renderer.rb
158
160
  - lib/trailblazer/diagram/bpmn.rb
159
161
  - trailblazer-developer.gemspec
160
162
  homepage: http://trailblazer.to
@@ -176,8 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
176
178
  - !ruby/object:Gem::Version
177
179
  version: '0'
178
180
  requirements: []
179
- rubyforge_project:
180
- rubygems_version: 2.7.3
181
+ rubygems_version: 3.0.8
181
182
  signing_key:
182
183
  specification_version: 4
183
184
  summary: Developer tools for Trailblazer.
@@ -1,36 +0,0 @@
1
- inherit_from:
2
- - https://raw.githubusercontent.com/trailblazer/meta/master/rubocop.yml
3
-
4
- AllCops:
5
- TargetRubyVersion: 2.5
6
- Exclude:
7
- - 'test/hash/bla.rb'
8
-
9
- Metrics/LineLength:
10
- Exclude:
11
- - test/diagram_test.rb
12
-
13
- Naming/MethodName:
14
- Enabled: false
15
-
16
- Style/ClassAndModuleChildren:
17
- Enabled: false
18
-
19
- # DISCUSS: user map instead of collect
20
- Style/CollectionMethods:
21
- Enabled: false
22
-
23
- # DISCUSS: Use raise with an explicit exception class and message, rather than just a message
24
- Style/ImplicitRuntimeError:
25
- Enabled: false
26
-
27
- Style/Lambda:
28
- EnforcedStyle: literal
29
-
30
- # DISCUSS: Use fail instead of raise to signal exceptions
31
- Style/SignalException:
32
- Enabled: false
33
-
34
- # DISUSS: this could be false because we have if locals blabla
35
- Bundler/DuplicatedGem:
36
- Enabled: false