y_support 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/y_support/local_object.rb +10 -6
- data/lib/y_support/misc.rb +0 -1
- data/lib/y_support/name_magic.rb +50 -76
- data/lib/y_support/version.rb +1 -1
- data/lib/y_support.rb +2 -30
- data/test/misc_test.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 759b0ff1cab2ec03f748370b5cf7914ba85fffd7
|
4
|
+
data.tar.gz: 05aa1789b0a44fac0e98a7e3f1be9dc9bd77e726
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ce6a5309f0d05cfc049bc2ad4264465e05a41320863257e318a15895a3f7e33608e90d2c479305d05120073e351446404130c9989d6f870f9f0f64de99e4b81
|
7
|
+
data.tar.gz: 458aa7e250fc6e902e6943fd6d74cd5a49ffe3ef84b334f62022fb3d8b19750b0393109f6fa4ad28a29ffa8018ee30750c9a2012d4f1170b3e8899bb955a2326
|
@@ -4,7 +4,7 @@ require 'y_support'
|
|
4
4
|
|
5
5
|
# Object, whose business is to stay local to methods. Optional signature
|
6
6
|
# provides additional level of safety in ensuring object locality. (Signature
|
7
|
-
# accessor is :signature, aliased as
|
7
|
+
# accessor is :signature, aliased as :σ, small Greek sigma.)
|
8
8
|
#
|
9
9
|
class LocalObject
|
10
10
|
attr_reader :signature
|
@@ -13,23 +13,27 @@ class LocalObject
|
|
13
13
|
# Optional argument signature provides additional level of safety in
|
14
14
|
# ascertaining that the object indeed is of local origin.
|
15
15
|
#
|
16
|
-
def initialize signature=
|
17
|
-
@signature=signature
|
16
|
+
def initialize signature=caller_locations( 1, 1 )[0].label
|
17
|
+
@signature = signature
|
18
18
|
end
|
19
19
|
|
20
20
|
# True if the (optional) signature matches.
|
21
21
|
#
|
22
|
-
def local_object? signature=
|
22
|
+
def local_object? signature=caller_locations( 1, 1 )[0].label
|
23
23
|
signature == self.signature
|
24
24
|
end
|
25
25
|
alias ℓ? local_object?
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
# Object class is patched with #LocalObject (alias L!) constructor, and
|
29
|
+
# #local_object?, alias #ℓ? inquirer.
|
30
|
+
#
|
29
31
|
class Object
|
30
32
|
# LocalObject constructor.
|
31
33
|
#
|
32
|
-
def LocalObject signature=
|
34
|
+
def LocalObject signature=caller_locations( 1, 1 )[0].label
|
35
|
+
LocalObject.new signature
|
36
|
+
end
|
33
37
|
alias L! LocalObject
|
34
38
|
|
35
39
|
# False for normal objects, overriden in the LocalObject class.
|
data/lib/y_support/misc.rb
CHANGED
data/lib/y_support/name_magic.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# -*- coding: utf-8 -*-
|
2
2
|
require 'y_support'
|
3
3
|
|
4
4
|
# A mixin imitating Ruby constant magic, plus automation of :name alias :ɴ
|
@@ -24,23 +24,20 @@ require 'y_support'
|
|
24
24
|
#
|
25
25
|
module NameMagic
|
26
26
|
DEBUG = false
|
27
|
-
PROBLEM_MODULES = [ 'Gem', 'Rack', 'ActiveSupport' ]
|
28
27
|
|
29
28
|
def self.included target
|
30
29
|
case target
|
31
|
-
when Class then
|
30
|
+
when Class then # we will decorate its #new method
|
32
31
|
class << target
|
33
|
-
# Make space
|
34
|
-
alias :original_method_new :new
|
32
|
+
alias :original_method_new :new # Make space to decorate #new
|
35
33
|
end
|
36
34
|
# Attach the decorators etc.
|
37
35
|
target.extend ::NameMagic::ClassMethods
|
38
36
|
target.extend ::NameMagic::NamespaceMethods
|
39
37
|
# Attach namespace methods to also to the namespace, if given.
|
40
38
|
begin
|
41
|
-
|
42
|
-
target.namespace
|
43
|
-
end
|
39
|
+
target.namespace.extend ::NameMagic::NamespaceMethods unless
|
40
|
+
target.namespace == target
|
44
41
|
rescue NoMethodError
|
45
42
|
end
|
46
43
|
else # it is a Module; we'll infect it with this #included method
|
@@ -50,13 +47,13 @@ module NameMagic
|
|
50
47
|
target.method( :pre_included )
|
51
48
|
rescue NameError
|
52
49
|
end
|
53
|
-
if pre_included_of_the_target then
|
50
|
+
if pre_included_of_the_target then # target has #pre_included hook
|
54
51
|
target.define_singleton_method :included do |ç|
|
55
52
|
pre_included_of_the_target.( ç )
|
56
53
|
included_of_self.call( ç )
|
57
54
|
included_of_the_target.call( ç )
|
58
55
|
end
|
59
|
-
else
|
56
|
+
else # target has no #pre_included hook
|
60
57
|
target.define_singleton_method :included do |ç|
|
61
58
|
included_of_self.( ç )
|
62
59
|
included_of_the_target.( ç )
|
@@ -101,8 +98,7 @@ module NameMagic
|
|
101
98
|
# Names an instance, aggresively (overwrites existing names).
|
102
99
|
#
|
103
100
|
def name!( ɴ )
|
104
|
-
|
105
|
-
old_ɴ = self.class.__instances__[ self ]
|
101
|
+
old_ɴ = self.class.__instances__[ self ] # get instance's old name, if any
|
106
102
|
# honor the hook
|
107
103
|
name_set_closure = self.class.instance_variable_get :@name_set_closure
|
108
104
|
ɴ = name_set_closure.( ɴ, self, old_ɴ ) if name_set_closure
|
@@ -111,7 +107,7 @@ module NameMagic
|
|
111
107
|
# otherwise, rudely remove the collider, if any
|
112
108
|
pair = self.class.__instances__.rassoc( ɴ )
|
113
109
|
self.class.__forget__( pair[0] ) if pair
|
114
|
-
# and add
|
110
|
+
# and add self to the namespace instead
|
115
111
|
self.class.namespace.const_set ɴ, self # write a constant
|
116
112
|
self.class.__instances__[ self ] = ɴ # write to __instances__
|
117
113
|
self.class.__forget__ old_ɴ # forget the old name of self
|
@@ -155,10 +151,10 @@ module NameMagic
|
|
155
151
|
self
|
156
152
|
end
|
157
153
|
|
158
|
-
# Returns
|
159
|
-
# argument
|
160
|
-
#
|
161
|
-
#
|
154
|
+
# Returns an instance identiified by the argument. NameError is raised, if
|
155
|
+
# the argument does not identify an instance. (It can be an instance name
|
156
|
+
# as string, symbol, or an instance itself, in which case it is merely
|
157
|
+
# returned without changes.)
|
162
158
|
#
|
163
159
|
def instance arg
|
164
160
|
const_magic
|
@@ -224,7 +220,7 @@ module NameMagic
|
|
224
220
|
}
|
225
221
|
end
|
226
222
|
alias :forget_nameless_instances :forget_anonymous_instances
|
227
|
-
|
223
|
+
|
228
224
|
# Clears class-owned references to all the instances.
|
229
225
|
#
|
230
226
|
def forget_all_instances
|
@@ -261,35 +257,22 @@ module NameMagic
|
|
261
257
|
# Checks all the constants in some module's namespace, recursively.
|
262
258
|
#
|
263
259
|
def serve_all_modules
|
264
|
-
|
265
|
-
|
266
|
-
ObjectSpace.each_object Module do |ɱ|
|
267
|
-
# hack against bugs when getting constants from URI
|
268
|
-
next if ::NameMagic::PROBLEM_MODULES.any? { |problem_ς|
|
269
|
-
begin
|
270
|
-
ɱ.name.to_s.start_with? problem_ς
|
271
|
-
rescue NoMethodError, ArgumentError
|
272
|
-
end
|
273
|
-
}
|
260
|
+
todo = ( nameless_instances + __avid_instances__ ).map( &:object_id ).uniq
|
261
|
+
ObjectSpace.each_object Module do |ɱ| # for all the modules...
|
274
262
|
puts ɱ if ::NameMagic::DEBUG
|
275
|
-
#
|
276
|
-
|
277
|
-
begin # insurance against buggy dynamic loading of constants
|
263
|
+
ɱ.constants( false ).each do |const_ß| # and all the constants...
|
264
|
+
begin # insurance against constant dynamic loading fails
|
278
265
|
◉ = ɱ.const_get( const_ß )
|
279
|
-
rescue
|
266
|
+
rescue LoadError, StandardError
|
280
267
|
next
|
281
268
|
end
|
282
|
-
# is it a wanted object?
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
◉.name! const_ß # and then name it rudely
|
290
|
-
else # name this anonymous instance cautiously
|
291
|
-
# honor name_set_closure
|
292
|
-
ɴ = if @name_set_closure then
|
269
|
+
if todo.include? ◉.object_id then # is it a wanted object?
|
270
|
+
if __avid_instances__.map( &:object_id ).include? ◉.object_id # avid
|
271
|
+
__avid_instances__ # 1. remove from avid list
|
272
|
+
.delete_if { |instance| instance.object_id == ◉.object_id }
|
273
|
+
◉.name! const_ß # 2. name rudely
|
274
|
+
else # not avid
|
275
|
+
ɴ = if @name_set_closure then # honor name_set_closure
|
293
276
|
@name_set_closure.( const_ß, ◉, nil )
|
294
277
|
else const_ß end
|
295
278
|
ɴ = validate_capitalization( ɴ ).to_sym
|
@@ -301,14 +284,12 @@ module NameMagic
|
|
301
284
|
raise NameError, "Another #{self} named '#{ɴ}' already " +
|
302
285
|
"exists!" unless conflicter == ◉
|
303
286
|
else
|
304
|
-
# add the instance to the namespace
|
305
|
-
|
306
|
-
namespace.const_set ɴ, ◉
|
287
|
+
__instances__[ ◉ ] = ɴ # add the instance to the namespace
|
288
|
+
namespace.const_set ɴ, ◉ # add the instance to the namespace
|
307
289
|
end
|
308
290
|
end
|
309
|
-
|
310
|
-
|
311
|
-
break if incriminated_ids.empty?
|
291
|
+
todo.delete ◉.object_id # remove the id from todo list
|
292
|
+
break if todo.empty?
|
312
293
|
end
|
313
294
|
end # each
|
314
295
|
end # each_object Module
|
@@ -316,7 +297,7 @@ module NameMagic
|
|
316
297
|
|
317
298
|
# Checks whether a name starts with a capital letter.
|
318
299
|
#
|
319
|
-
def validate_capitalization
|
300
|
+
def validate_capitalization name
|
320
301
|
ɴ = name.to_s
|
321
302
|
# check whether the name starts with 'A'..'Z'
|
322
303
|
raise NameError, "#{self.class} name must start with a capital " +
|
@@ -326,48 +307,41 @@ module NameMagic
|
|
326
307
|
end
|
327
308
|
|
328
309
|
module ClassMethods
|
329
|
-
# In addition to
|
330
|
-
#
|
331
|
-
#
|
332
|
-
#
|
310
|
+
# In addition to 'constant magic' ability (name upon constant assignment),
|
311
|
+
# NameMagic redefines class method #new so that it eats parameter :name,
|
312
|
+
# alias :ɴ, and takes care of naming the instance accordingly. Option
|
313
|
+
# :name_avid can also be supplied (true/false), which makes the naming
|
314
|
+
# avid if true. (Avid, or aggresive naming means that the instance being
|
315
|
+
# named overwrites whatever was stored under that name earlier.)
|
333
316
|
#
|
334
317
|
def new *args, &block
|
335
318
|
oo = args[-1].is_a?( Hash ) ? args.pop : {} # extract hash
|
336
|
-
|
337
|
-
|
338
|
-
elsif oo[:ɴ] then oo.delete :ɴ
|
319
|
+
ɴß = if oo[:name] then oo.delete :name # consume :name if supplied
|
320
|
+
elsif oo[:ɴ] then oo.delete :ɴ # consume :ɴ if supplied
|
339
321
|
else nil end
|
340
|
-
|
341
|
-
|
342
|
-
# Avoid name collisions unless avid
|
322
|
+
avid = oo[:name_avid] ? oo.delete( :name_avid ) : false # => true/false
|
323
|
+
# Avoid overwriting existing names unless avid:
|
343
324
|
raise NameError, "#{self} instance #{ɴß} already exists!" if
|
344
325
|
__instances__.keys.include? ɴß unless avid
|
345
|
-
#
|
326
|
+
# Instantiate:
|
346
327
|
args << oo unless oo.empty? # fuse hash
|
347
328
|
new_inst = original_method_new *args, &block
|
348
|
-
|
349
|
-
__instances__.merge! new_inst => nil
|
329
|
+
__instances__.merge! new_inst => nil # Instance is created unnamed
|
350
330
|
# honor the hook
|
351
|
-
@new_instance_closure.
|
352
|
-
|
353
|
-
# (avid instances will steal names from their competitors)
|
354
|
-
if ɴß then
|
331
|
+
@new_instance_closure.( new_inst ) if @new_instance_closure
|
332
|
+
if ɴß then # name was supplied, name the instance
|
355
333
|
if avid then new_inst.name! ɴß else new_inst.name = ɴß end
|
356
|
-
else
|
334
|
+
else # name wasn't supplied, make the instance avid
|
357
335
|
__avid_instances__ << new_inst
|
358
336
|
end
|
359
|
-
# return the new instance
|
360
|
-
return new_inst
|
337
|
+
return new_inst # return the new instance
|
361
338
|
end
|
362
339
|
|
363
|
-
#
|
364
|
-
# concerns about overwriting existing named instances.
|
340
|
+
# Calls #new in avid mode (name_avid: true).
|
365
341
|
#
|
366
342
|
def new! *args, &block
|
367
|
-
# extract options
|
368
|
-
|
369
|
-
# and call #new with added name_avid: true
|
370
|
-
new *args, oo.merge!( name_avid: true )
|
343
|
+
oo = args[-1].is_a?( Hash ) ? args.pop : {} # extract options
|
344
|
+
new *args, oo.merge!( name_avid: true ), &block
|
371
345
|
end
|
372
346
|
end # module ClassMethods
|
373
347
|
end # module NameMagic
|
data/lib/y_support/version.rb
CHANGED
data/lib/y_support.rb
CHANGED
@@ -1,33 +1,5 @@
|
|
1
1
|
#encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
# What follows is a commented-out list of interesting StdLibs. They may
|
6
|
-
# or may no be required in various parts of y_support.
|
3
|
+
# YSupport is a collection of methods used in Y gems.
|
7
4
|
#
|
8
|
-
|
9
|
-
# require 'mathn'
|
10
|
-
# require 'set'
|
11
|
-
# require 'csv'
|
12
|
-
|
13
|
-
# What follows is a commented-out list of interesting ActiveSupport parts.
|
14
|
-
# These may or may not be required in various parts of y_support.
|
15
|
-
#
|
16
|
-
# require 'active_support/core_ext/module/delegation'
|
17
|
-
# require 'active_support/core_ext/object/blank' # in object/misc.rb, string/misc.rb
|
18
|
-
# require 'active_support/core_ext/object/duplicable'
|
19
|
-
# require 'active_support/core_ext/string/starts_ends_with'
|
20
|
-
# require 'active_support/core_ext/string/strip'
|
21
|
-
# require 'active_support/core_ext/string/inflections' # in autoreq; module/misc.rb
|
22
|
-
# require 'active_support/core_ext/integer/multiple'
|
23
|
-
# require 'active_support/core_ext/integer/inflections'
|
24
|
-
# require 'active_support/core_ext/enumerable'
|
25
|
-
# require 'active_support/core_ext/array/extract_options'
|
26
|
-
# require 'active_support/core_ext/hash/conversions' # such as #to_xml
|
27
|
-
# require 'active_support/core_ext/hash/reverse_merge' # aliased in hash/misc.rb
|
28
|
-
# require 'active_support/core_ext/hash/deep_merge'
|
29
|
-
# require 'active_support/core_ext/hash/diff'
|
30
|
-
# require 'active_support/core_ext/hash/except'
|
31
|
-
# require 'active_support/core_ext/hash/keys'
|
32
|
-
# require 'active_support/core_ext/hash/slice'
|
33
|
-
# require 'active_support/core_ext/hash/indifferent_access'
|
5
|
+
require "y_support/version"
|
data/test/misc_test.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: y_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- boris
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|