activefacts-api 1.6.0 → 1.7.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
  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