activefacts-api 1.6.0 → 1.7.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
  SHA1:
3
- metadata.gz: e0575368e36de9bcdb5ccec88a51326b01714ba3
4
- data.tar.gz: 429c0170ab64f042f7e5ea0a2f14cd2ef5695965
3
+ metadata.gz: a80ac6cfb494e2b05728351858aa283a569caa5b
4
+ data.tar.gz: d5abea27b67b2501f16819de68c5716350423940
5
5
  SHA512:
6
- metadata.gz: e763cc4c8dee02074532ecd91289267d07e1b8f6c42e1eb5daa59b0dbbfdf1c9814673dac6fe05c0ca37f9b339755a68391cedd80939b844b3797589cb02818a
7
- data.tar.gz: 11e8b5774f723d2d0817cc37fd4510bbb04248b41697d39a745314f7cec83cea2dfc3945e7a5def7846aa6e1a172555b8ceeae33c1ec529c9869bc172d3cd94f
6
+ metadata.gz: 63bcb8b0e4b562ed566ea33f286469d11ba5ddce18f59cb58b66e45d5b78d94bc0643c171b8375d6d6a5d10d19aec7a5678cd42d15ab657aa53519fe05c13005
7
+ data.tar.gz: 8a0768e8cfe086e62ada27b327e1b9a049c4825efd0fdb925a9f6ccc85ef3873ba06a79a757ee27014bb13a86adfe6e9c4ec2374d3395f56988193523bd2f5ee
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.6.0
1
+ 1.7.0
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: activefacts-api 1.6.0 ruby lib
5
+ # stub: activefacts-api 1.7.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "activefacts-api"
9
- s.version = "1.6.0"
9
+ s.version = "1.7.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Clifford Heath"]
14
- s.date = "2015-02-24"
14
+ s.date = "2015-03-06"
15
15
  s.description = "\nThe ActiveFacts API is a Ruby DSL for managing constellations of elementary facts.\nEach fact is either existential (a value or an entity), characteristic (boolean) or\nbinary relational (A rel B). Relational facts are consistently co-referenced, so you\ncan traverse them efficiently in any direction. Each constellation maintains constraints\nover the fact population.\n"
16
16
  s.email = "clifford.heath@gmail.com"
17
17
  s.extra_rdoc_files = [
@@ -1,9 +1,39 @@
1
1
  #
2
- # ActiveFacts Support code.
3
- # The trace method supports indented tracing.
4
- # Set the TRACE environment variable to enable it. Search the code to find the TRACE keywords, or use "all".
2
+ # ActiveFacts Tracer.
5
3
  #
6
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
4
+ # The trace() method supports indented tracing.
5
+ #
6
+ # The first argument is normally a symbol which is the key for related trace calls.
7
+ # Set the TRACE environment variable to enable it, or add trace.enable(:key) to a CLI.
8
+ #
9
+ # Each subsequent argument is either
10
+ # - a String (or anything that can be join()ed), or
11
+ # - a Proc (or anything that can be called) that returns such a string.
12
+ # Proc arguments will be called only if the trace key is enabled.
13
+ # If the key is enabled (or not present) the Trace strings will be joined and emitted.
14
+ #
15
+ # A block passed to the trace method will always be called, and trace will always return its value.
16
+ # Any trace emitted from within such a block will be indented if the current trace key is enabled.
17
+ #
18
+ # As a special case, a call to trace with a key ending in _ is enabled if the base key is
19
+ # enabled, but enabled all nested calls to trace whether or not their key is enabled.
20
+ #
21
+ # A call to trace with a key but without a block will return true if the key is enabled
22
+ #
23
+ # A call to trace with no arguments returns the Tracer object itself.
24
+ #
25
+ # Built-in trace key behaviour:
26
+ # help - list (at exit) all trace keys that became available during the run
27
+ # all - enable all trace keys
28
+ # keys - display trace keys on every trace message (automatically enabled by :all)
29
+ # debug - prepare a Ruby debugger at the start of the run, so it has the full context available
30
+ # firstaid - stop inside the constructor for any exception so you can inspect the local context of the cause
31
+ # trap - trap SIGINT (^C) in a block that allows inspecting or continuing execution (not all debuggers support this)
32
+ # flame - use ruby-prof-flamegraph to display the performance profile as a flame graph using SVG
33
+ #
34
+ # The debugger is chosen from ENV['DEBUG_PREFERENCE'] or the first to load of: byebug, pry. debugger, ruby-trace
35
+ #
36
+ # Copyright (c) 2009-2015 Clifford Heath. Read the LICENSE file.
7
37
  #
8
38
  module ActiveFacts
9
39
  (class << self; self; end).class_eval do
@@ -12,130 +42,193 @@ module ActiveFacts
12
42
 
13
43
  class Tracer
14
44
  def initialize
45
+ @indent = 0 # Current nesting level of enabled trace blocks
15
46
  @nested = false # Set when a block enables all enclosed tracing
16
- @available = {}
47
+ @available = {} # Hash of available trace keys, accumulated during the run
17
48
 
18
- # First time, initialise the tracing environment
19
- @indent = 0
20
49
  @keys = {}
21
- if (e = ENV[@@trace_name ||= "TRACE"])
22
- e.split(/[^_a-zA-Z0-9]/).each{|k| enable(k) }
23
- if @keys[:help]
24
- at_exit {
25
- @stderr.puts "---\nDebugging keys available: #{@available.keys.map{|s| s.to_s}.sort*", "}"
26
- }
27
- end
28
- if @keys[:debug]
29
- errors = []
30
- success = false
31
- (
32
- [ENV["DEBUG_PREFERENCE"]].compact +
33
- [
34
- 'byebug',
35
- 'pry',
36
- 'debugger',
37
- 'ruby-debug'
38
- ]
39
- ).each do |debugger|
40
- begin
41
- require debugger
42
- puts "Loaded "+debugger
43
- if debugger == 'byebug'
44
- Kernel.class_eval do
45
- alias_method :byebug, :debugger
46
- end
47
- end
48
- success = true
49
- break
50
- rescue LoadError => e
51
- errors << e
52
- end
53
- end
54
- unless success
55
- puts "Can't load any debugger, failed on:\n#{errors.inspect}"
56
- end
57
- ::Debugger.start rescue nil
58
- end
50
+ if (e = ENV["TRACE"])
51
+ e.split(/[^_a-zA-Z0-9]/).each{|k| enable(k) }
59
52
  end
60
53
  end
61
54
 
62
- def keys
55
+ def trace(*args, &block)
56
+ begin
57
+ old_indent, old_nested, enabled = @indent, @nested, show(*args)
58
+ # Apologies for this monstrosity, but it reduces the steps when single-stepping:
59
+ block ? yield : (args.size == 0 ? self : (enabled == 1 ? true : false))
60
+ ensure
61
+ @indent, @nested = old_indent, old_nested
62
+ end
63
+ end
64
+
65
+ def available_keys
63
66
  @available.keys
64
67
  end
65
68
 
66
- def enabled key
69
+ def enabled? key
67
70
  !key.empty? && @keys[key.to_sym]
68
71
  end
69
72
 
70
73
  def enable key
71
- !key.to_s.empty? && @keys[key.to_sym] = true
74
+ if !key.empty? && !@keys[s = key.to_sym]
75
+ @keys[s] = true
76
+ setup_help if s == :help
77
+ setup_flame if s == :flame
78
+ else
79
+ true
80
+ end
72
81
  end
73
82
 
74
83
  def disable key
75
- !key.to_s.empty? && @keys.delete(key.to_sym)
84
+ !key.empty? and @keys.delete(key.to_sym)
76
85
  end
77
86
 
78
87
  def toggle key
79
- !key.to_s.empty? and enabled(key) ? (disable(key); false) : (enable(key); true)
88
+ if !key.empty?
89
+ if enabled?(key)
90
+ disable(key)
91
+ false
92
+ else
93
+ enable(key)
94
+ true
95
+ end
96
+ end
80
97
  end
81
98
 
82
- def selected(args)
83
- # Figure out whether this trace is enabled (itself or by :all), if it nests, and if we should print the key:
84
- key =
85
- if Symbol === args[0]
86
- control = args.shift
87
- if (s = control.to_s) =~ /_\Z/
88
- nested = true
89
- s.sub(/_\Z/, '').to_sym # Avoid creating new strings willy-nilly
90
- else
91
- control
92
- end
93
- else
94
- :all
95
- end
99
+ def setup_help
100
+ at_exit {
101
+ $stderr.puts "---\nTracing keys available: #{@available.keys.map{|s| s.to_s}.sort*", "}"
102
+ }
103
+ end
96
104
 
97
- @available[key] ||= key # Remember that this trace was requested, for help
98
- enabled = @nested || # This trace is enabled because it's in a nested block
99
- @keys[key] || # This trace is enabled in its own right
100
- @keys[:all] # This trace is enabled because all are
101
- @nested = nested
102
- [
103
- (enabled ? 1 : 0),
104
- @keys[:all] ? " %-15s"%control : nil
105
- ]
105
+ def setup_flame
106
+ require 'ruby-prof'
107
+ require 'ruby-prof-flamegraph'
108
+ profile_result = RubyProf.start
109
+ at_exit {
110
+ profile_result2 = RubyProf.stop
111
+ printer = RubyProf::FlameGraphPrinter.new(profile_result2)
112
+ data_file = "/tmp/flamedata_#{Process.pid}.txt"
113
+ svg_file = "/tmp/flamedata_#{Process.pid}.svg"
114
+ flamegraph = File.dirname(__FILE__)+"/flamegraph.pl"
115
+ File.popen("tee #{data_file} | perl #{flamegraph} --countname=ms --width=4800 > #{svg_file}", "w") { |f|
116
+ printer.print(f, {})
117
+ }
118
+ STDERR.puts("Flame graph dumped to file:///#{svg_file}")
119
+ }
120
+ end
121
+
122
+ def setup_debugger
123
+ begin
124
+ require 'ruby-trace '
125
+ Debugger.start # (:post_mortem => true) # Some Ruby versions crash on post-mortem debugging
126
+ rescue LoadError
127
+ # Ok, no debugger, tough luck.
128
+ end
129
+
130
+ (
131
+ [ENV["DEBUG_PREFERENCE"]].compact +
132
+ [
133
+ 'byebug',
134
+ 'pry',
135
+ 'debugger',
136
+ 'ruby-trace '
137
+ ]
138
+ ).each do |debugger|
139
+ begin
140
+ require debugger
141
+ if debugger == 'byebug'
142
+ Kernel.class_eval do
143
+ alias_method :byebug, :debugger
144
+ end
145
+ end
146
+ ::Debugger.start if (const_get(::Debugger) rescue nil)
147
+ break
148
+ rescue LoadError => e
149
+ errors << e
150
+ end
151
+ end
152
+
153
+ if trace :trap
154
+ trap('SIGINT') do
155
+ puts "Stopped at:\n\t"+caller*"\n\t"
156
+ debugger
157
+ true # Stopped on SIGINT
158
+ end
159
+ end
106
160
  end
107
161
 
162
+ def setup_firstaid
163
+ if trace :firstaid
164
+ puts "Preparing first aid kit"
165
+ ::Exception.class_eval do
166
+ alias_method :firstaid_initialize, :initialize
167
+
168
+ def initialize *args, &b
169
+ send(:firstaid_initialize, *args, &b)
170
+ puts "Stopped due to #{self.class}: #{message} at "+caller*"\n\t"
171
+ debugger
172
+ true # Stopped in Exception constructor
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ private
108
179
  def show(*args)
109
- enabled, key_to_show = selected(args)
180
+ enabled, key_to_show = selected?(args)
110
181
 
111
182
  # Emit the message if enabled or a parent is:
112
183
  if args.size > 0 && enabled == 1
113
- puts "\##{key_to_show} " +
114
- ' '*@indent +
115
- args.
116
- # A laudable aim, certainly, but in practise the Procs leak and slow things down:
117
- # map{|a| a.respond_to?(:call) ? a.call : a}.
118
- join(' ')
184
+ puts "\##{key_to_show} " +
185
+ ' '*@indent +
186
+ args.
187
+ map{|a| a.respond_to?(:call) ? a.call : a}.
188
+ join(' ')
119
189
  end
120
190
  @indent += enabled
121
191
  enabled
122
192
  end
123
193
 
124
- def trace(*args, &block)
125
- begin
126
- old_indent, old_nested, enabled = @indent, @nested, show(*args)
127
- return (block || proc { enabled == 1 }).call
128
- ensure
129
- @indent, @nested = old_indent, old_nested
130
- end
194
+ def selected?(args)
195
+ # Figure out whether this trace is enabled (itself or by :all), if it nests, and if we should print the key:
196
+ key =
197
+ if Symbol === args[0]
198
+ control = args.shift
199
+ if (s = control.to_s) =~ /_\Z/
200
+ nested = true
201
+ s.sub(/_\Z/, '').to_sym # Avoid creating new strings willy-nilly
202
+ else
203
+ control
204
+ end
205
+ else
206
+ :all
207
+ end
208
+
209
+ @available[key] ||= key # Remember that this trace was requested, for help
210
+ enabled = @nested || # This trace is enabled because it's in a nested block
211
+ @keys[key] || # This trace is enabled in its own right
212
+ @keys[:all] # This trace is enabled because all are
213
+ @nested = nested
214
+ [
215
+ (enabled ? 1 : 0),
216
+ @keys[:keys] || @keys[:all] ? " %-15s"%control : nil
217
+ ]
131
218
  end
219
+
132
220
  end
133
221
  end
134
222
 
223
+ # Make the trace method globally available:
135
224
  class Object
136
225
  def trace *args, &block
137
226
  (ActiveFacts.tracer ||= ActiveFacts::Tracer.new).trace(*args, &block)
138
227
  end
139
228
  end
140
229
 
141
- trace ''
230
+ # Load the ruby debugger before everything else, if requested
231
+ if trace(:debug) or trace(:firstaid) or trace(:trap)
232
+ trace.setup_debugger
233
+ trace.setup_firstaid
234
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activefacts-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clifford Heath
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-24 00:00:00.000000000 Z
11
+ date: 2015-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbtree-pure