pluggability 0.9.0 → 0.10.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/History.md +8 -0
- data/lib/pluggability.rb +48 -31
- data/spec/helpers.rb +17 -8
- data/spec/pluggability_spec.rb +27 -7
- data.tar.gz.sig +0 -0
- metadata +27 -28
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: acdddb8e543aa6046ffbdbd68d67588eed0cb3ba2ab70bf2f2c1ea8fb5e55e86
|
4
|
+
data.tar.gz: 06e1b5426c52c27250e940a401327a6176ce666d22b7cba988746c85de96cb95
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f84aae2fa72d6425a69592bb4ea1fcc37e6e5dc96d9b03ab1f6c5d2954f86806f4316dd4e9baf0cb7111ffb1f9b2d682c43b44305750f84a66afb8faaf738368
|
7
|
+
data.tar.gz: 01bc40509082e86090d3770491e15473b0fdf5cabbb3021ec8bfdf4a9e56b73f579e43cfcebf5909454da4ec1802bae201ad68ea2107281ae7a15bc24e9bfaed
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/History.md
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
---
|
4
4
|
|
5
|
+
## v0.10.0 [2025-07-12] Michael Granger <ged@faeriemud.org>
|
6
|
+
|
7
|
+
Improvements:
|
8
|
+
|
9
|
+
- Remove support for non-Ruby idiomatic plugin paths
|
10
|
+
- Add support for newer Ruby features, e.g., Module#set_temporary_name.
|
11
|
+
|
12
|
+
|
5
13
|
## v0.9.0 [2023-06-08] Michael Granger <ged@faeriemud.org>
|
6
14
|
|
7
15
|
Improvements:
|
data/lib/pluggability.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
-
#encoding: utf-8
|
3
2
|
|
4
3
|
require 'loggability' unless defined?( Loggability )
|
5
4
|
|
5
|
+
|
6
6
|
# The Pluggability module
|
7
7
|
module Pluggability
|
8
8
|
extend Loggability
|
@@ -12,7 +12,7 @@ module Pluggability
|
|
12
12
|
|
13
13
|
|
14
14
|
# Library version
|
15
|
-
VERSION = '0.
|
15
|
+
VERSION = '0.10.0'
|
16
16
|
|
17
17
|
|
18
18
|
# An exception class for Pluggability specific errors.
|
@@ -20,12 +20,26 @@ module Pluggability
|
|
20
20
|
FactoryError = PluginError
|
21
21
|
|
22
22
|
|
23
|
+
module StringRefinements
|
24
|
+
refine( String ) do
|
25
|
+
|
26
|
+
def uncamelcase
|
27
|
+
return self.gsub( /([a-z0-9])([A-Z])/, "\\1_\\2" )
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
using StringRefinements
|
33
|
+
|
34
|
+
|
23
35
|
### Add the @derivatives instance variable to including classes.
|
24
36
|
def self::extend_object( obj )
|
25
37
|
obj.instance_variable_set( :@plugin_prefixes, [] )
|
26
38
|
obj.instance_variable_set( :@plugin_exclusions, [] )
|
27
39
|
obj.instance_variable_set( :@derivatives, {} )
|
28
40
|
|
41
|
+
obj.singleton_class.attr_accessor( :plugin_name )
|
42
|
+
|
29
43
|
Pluggability.pluggable_classes << obj
|
30
44
|
|
31
45
|
super
|
@@ -125,15 +139,30 @@ module Pluggability
|
|
125
139
|
return base.name
|
126
140
|
end
|
127
141
|
end
|
128
|
-
|
142
|
+
alias_method :factory_type, :plugin_type
|
129
143
|
|
130
144
|
|
131
145
|
### Inheritance callback -- Register subclasses in the derivatives hash
|
132
146
|
### so that ::create knows about them.
|
133
147
|
def inherited( subclass )
|
134
|
-
|
148
|
+
Pluggability.log.debug " %p inherited by %p" % [ self, subclass ]
|
149
|
+
self.register_plugin_type( subclass )
|
150
|
+
super
|
151
|
+
end
|
135
152
|
|
136
|
-
|
153
|
+
|
154
|
+
### Override Module#set_temporary_name so +new_name+ can be used to derive the
|
155
|
+
### plugin name. Note that this does *not* detect if you later assign the
|
156
|
+
### anonymous class to a constant and thus clear its temporary name.
|
157
|
+
def set_temporary_name( new_name )
|
158
|
+
super
|
159
|
+
self.register_plugin_type( self )
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
### Register the given +subclass+ as a plugin type of the receiving Pluggable class.
|
164
|
+
def register_plugin_type( subclass )
|
165
|
+
plugin_class = Pluggability.plugin_base_class( subclass )
|
137
166
|
keys = [ subclass ]
|
138
167
|
|
139
168
|
# If it's not an anonymous class, make some keys out of variants of its name
|
@@ -153,13 +182,8 @@ module Pluggability
|
|
153
182
|
plugin_class.derivatives[ key ] = subclass
|
154
183
|
end
|
155
184
|
|
156
|
-
|
157
|
-
|
158
|
-
attr_reader :plugin_name
|
159
|
-
end
|
160
|
-
subclass.instance_variable_set( :@plugin_name, keys.last )
|
161
|
-
|
162
|
-
super
|
185
|
+
Pluggability.log.debug "Setting plugin name of %p to %p" % [ subclass, keys.last ]
|
186
|
+
subclass.plugin_name = keys.last
|
163
187
|
end
|
164
188
|
|
165
189
|
|
@@ -168,19 +192,16 @@ module Pluggability
|
|
168
192
|
def make_derivative_names( subclass )
|
169
193
|
keys = []
|
170
194
|
|
171
|
-
|
195
|
+
# Order is important here, as the last non-nil one becomes the plugin_name.
|
196
|
+
simple_name = subclass.name.sub( /\A.*::/, '' ).sub( /\A(\w+).*/, '\\1' )
|
172
197
|
keys << simple_name << simple_name.downcase
|
173
|
-
keys << simple_name.
|
198
|
+
keys << simple_name.uncamelcase.downcase
|
174
199
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
keys << Regexp.last_match[1].downcase
|
179
|
-
else
|
180
|
-
keys << subclass.name.sub( /.*::/, '' ).downcase
|
181
|
-
end
|
200
|
+
simpler_name = simple_name.sub( /(?:#{self.plugin_type})\z/, '' )
|
201
|
+
keys << simpler_name << simpler_name.downcase
|
202
|
+
keys << simpler_name.uncamelcase.downcase
|
182
203
|
|
183
|
-
return keys
|
204
|
+
return keys.uniq
|
184
205
|
end
|
185
206
|
|
186
207
|
|
@@ -361,6 +382,7 @@ module Pluggability
|
|
361
382
|
|
362
383
|
candidate_paths = candidates.
|
363
384
|
flat_map {|path| Gem.find_latest_files( path ) }.
|
385
|
+
uniq.
|
364
386
|
reject {|path| self.is_excluded_path?( path ) || ! File.file?(path) }
|
365
387
|
Pluggability.log.debug "Valid candidates in the current gemset: %p" % [ candidate_paths ]
|
366
388
|
|
@@ -374,7 +396,7 @@ module Pluggability
|
|
374
396
|
prefixes = self.plugin_prefixes
|
375
397
|
prefixes << '' if prefixes.empty?
|
376
398
|
|
377
|
-
return prefixes.flat_map {|pre| self.make_require_path(mod_name, pre) }
|
399
|
+
return prefixes.flat_map {|pre| self.make_require_path(mod_name, pre) }.uniq
|
378
400
|
end
|
379
401
|
|
380
402
|
|
@@ -385,17 +407,12 @@ module Pluggability
|
|
385
407
|
### "drivers/SocketDataDriver", "drivers/socket", "drivers/Socket"]
|
386
408
|
def make_require_path( modname, subdir )
|
387
409
|
path = []
|
388
|
-
myname = self.plugin_type
|
410
|
+
myname = self.plugin_type.uncamelcase.downcase
|
411
|
+
modname = modname.uncamelcase.downcase
|
389
412
|
|
390
413
|
# Make permutations of the two parts
|
391
414
|
path << modname
|
392
|
-
path << modname
|
393
|
-
path << modname + myname
|
394
|
-
path << modname.downcase + myname
|
395
|
-
path << modname.downcase + myname.downcase
|
396
|
-
path << modname + '_' + myname
|
397
|
-
path << modname.downcase + '_' + myname
|
398
|
-
path << modname.downcase + '_' + myname.downcase
|
415
|
+
path << modname + '_' + myname
|
399
416
|
|
400
417
|
# If a non-empty subdir was given, prepend it to all the items in the
|
401
418
|
# path
|
data/spec/helpers.rb
CHANGED
@@ -1,19 +1,28 @@
|
|
1
|
-
|
2
|
-
# coding: utf-8
|
1
|
+
# -*- ruby -*-
|
3
2
|
|
4
3
|
require 'rspec'
|
4
|
+
require 'diff/lcs'
|
5
5
|
require 'loggability/spechelpers'
|
6
6
|
require 'pluggability'
|
7
7
|
|
8
|
-
|
8
|
+
# Mock with Rspec
|
9
9
|
RSpec.configure do |config|
|
10
|
+
config.mock_with( :rspec ) do |mock|
|
11
|
+
mock.syntax = :expect
|
12
|
+
end
|
10
13
|
|
11
|
-
config.
|
14
|
+
config.disable_monkey_patching!
|
15
|
+
config.example_status_persistence_file_path = "spec/.status"
|
12
16
|
config.filter_run :focus
|
13
|
-
config.
|
14
|
-
|
15
|
-
config.
|
16
|
-
|
17
|
+
config.filter_run_when_matching :focus
|
18
|
+
config.order = :random
|
19
|
+
config.profile_examples = 5
|
20
|
+
config.run_all_when_everything_filtered = true
|
21
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
22
|
+
config.warnings = true
|
23
|
+
|
24
|
+
config.expect_with( :rspec ) do |expectations|
|
25
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
17
26
|
end
|
18
27
|
|
19
28
|
config.include( Loggability::SpecHelpers )
|
data/spec/pluggability_spec.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require_relative 'helpers'
|
4
4
|
|
5
5
|
require 'pluggability'
|
6
|
-
|
6
|
+
require 'loggability'
|
7
7
|
|
8
8
|
#
|
9
9
|
# Testing classes
|
@@ -34,7 +34,7 @@ class SubSubPlugin < SubPlugin; end
|
|
34
34
|
#
|
35
35
|
# Examples
|
36
36
|
#
|
37
|
-
describe Pluggability do
|
37
|
+
RSpec.describe Pluggability do
|
38
38
|
|
39
39
|
before( :each ) do
|
40
40
|
Plugin.plugin_exclusions = []
|
@@ -101,9 +101,9 @@ describe Pluggability do
|
|
101
101
|
at_least( :once ).
|
102
102
|
and_return( ['/some/path/to/plugins/dazzle.rb'] )
|
103
103
|
expect( Kernel ).to receive( :require ).with( '/some/path/to/plugins/dazzle.rb' ) do |*args|
|
104
|
-
loaded_class = Class.new( Plugin )
|
105
|
-
|
106
|
-
|
104
|
+
loaded_class = Class.new( Plugin ) do
|
105
|
+
set_temporary_name 'Plugin::Dazzle (testing class)'
|
106
|
+
end
|
107
107
|
true
|
108
108
|
end
|
109
109
|
|
@@ -111,11 +111,31 @@ describe Pluggability do
|
|
111
111
|
end
|
112
112
|
|
113
113
|
|
114
|
+
it "will load new plugins from the require path if given a camel-cased class name" do
|
115
|
+
loaded_class = nil
|
116
|
+
|
117
|
+
expect( Gem ).to receive( :find_latest_files ).
|
118
|
+
at_least( :once ).
|
119
|
+
and_return( ['/some/path/to/plugins/razzle_dazzle.rb'] )
|
120
|
+
expect( Kernel ).to receive( :require ) do |require_path|
|
121
|
+
expect( require_path ).to eq( '/some/path/to/plugins/razzle_dazzle.rb' )
|
122
|
+
|
123
|
+
loaded_class = Class.new( Plugin ) do
|
124
|
+
set_temporary_name 'Plugin::RazzleDazzle (testing class)'
|
125
|
+
end
|
126
|
+
|
127
|
+
true
|
128
|
+
end
|
129
|
+
|
130
|
+
expect( Plugin.create(:RazzleDazzle) ).to be_an_instance_of( loaded_class )
|
131
|
+
end
|
132
|
+
|
133
|
+
|
114
134
|
it "will output a sensible description of what it tried to load if requiring a " +
|
115
135
|
"derivative fails" do
|
116
136
|
|
117
137
|
# at least 6 -> 3 variants * 2 paths
|
118
|
-
expect( Gem ).to receive( :find_latest_files ).at_least(
|
138
|
+
expect( Gem ).to receive( :find_latest_files ).at_least( 4 ).times.
|
119
139
|
and_return( [] )
|
120
140
|
|
121
141
|
expect {
|
@@ -293,7 +313,7 @@ describe Pluggability do
|
|
293
313
|
|
294
314
|
|
295
315
|
it "still knows what the simplest version of its plugin name is" do
|
296
|
-
expect( SubSubPlugin.plugin_name ).to eq( '
|
316
|
+
expect( SubSubPlugin.plugin_name ).to eq( 'sub_sub' )
|
297
317
|
end
|
298
318
|
|
299
319
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,40 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pluggability
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Granger
|
8
8
|
- Martin Chase
|
9
|
-
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain:
|
12
11
|
- |
|
13
12
|
-----BEGIN CERTIFICATE-----
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
13
|
+
MIIEbDCCAtSgAwIBAgIBATANBgkqhkiG9w0BAQsFADA+MQwwCgYDVQQDDANnZWQx
|
14
|
+
GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
|
15
|
+
HhcNMjUwMTAxMDMzMTA5WhcNMjYwMTAxMDMzMTA5WjA+MQwwCgYDVQQDDANnZWQx
|
16
|
+
GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
|
17
|
+
ggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC/JWGRHO+USzR97vXjkFgt
|
18
|
+
83qeNf2KHkcvrRTSnR64i6um/ziin0I0oX23H7VYrDJC9A/uoUa5nGRJS5Zw/+wW
|
19
|
+
ENcvWVZS4iUzi4dsYJGY6yEOsXh2CcF46+QevV8iE+UmbkU75V7Dy1JCaUOyizEt
|
20
|
+
TH5UHsOtUU7k9TYARt/TgYZKuaoAMZZd5qyVqhF1vV+7/Qzmp89NGflXf2xYP26a
|
21
|
+
4MAX2qqKX/FKXqmFO+AGsbwYTEds1mksBF3fGsFgsQWxftG8GfZQ9+Cyu2+l1eOw
|
22
|
+
cZ+lPcg834G9DrqW2zhqUoLr1MTly4pqxYGb7XoDhoR7dd1kFE2a067+DzWC/ADt
|
23
|
+
+QkcqWUm5oh1fN0eqr7NsZlVJDulFgdiiYPQiIN7UNsii4Wc9aZqBoGcYfBeQNPZ
|
24
|
+
soo/6za/bWajOKUmDhpqvaiRv9EDpVLzuj53uDoukMMwxCMfgb04+ckQ0t2G7wqc
|
25
|
+
/D+K9JW9DDs3Yjgv9k4h7YMhW5gftosd+NkNC/+Y2CkCAwEAAaN1MHMwCQYDVR0T
|
26
|
+
BAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFHKN/nkRusdqCJEuq3lgB3fJvyTg
|
27
|
+
MBwGA1UdEQQVMBOBEWdlZEBGYWVyaWVNVUQub3JnMBwGA1UdEgQVMBOBEWdlZEBG
|
28
|
+
YWVyaWVNVUQub3JnMA0GCSqGSIb3DQEBCwUAA4IBgQBjrBzCKWzXFigswYSPzGO8
|
29
|
+
9atBtY/eQdcN6KCL+PTzQBD9yePGF7H/xsww3awRauP+D1VUjCFbiiC3Qb0Ww0Qd
|
30
|
+
OVA0s10T9KpZ8nb2XyKocSK7TfgDhcyr0V4H2MPxwK9SWYjGGh8z9z9HmT0i3PyX
|
31
|
+
fXOSzzEoG6u26HIOg0nxSpitEjiAHBekQxy9ka5NuQbxoxMg+eIHU4rU9IUhu0Rf
|
32
|
+
wl4wuvPVE3UQK0v0uqT6rJukEKQ1iNgK5R8klgEIv79XhQPgTkMt31FGfrwOp6HB
|
33
|
+
OE0HMwOwY9B0w3aOxxdMQyyRxaZVv3eWE5RimQI7T0TUaxPngtS33ByMZjTeidxi
|
34
|
+
ESIUEPVXoBCkFgLW1EVlBb+rG7WLYod4eVll4tKA42Bi2Ju90tqiJ1YQiyuRfCnp
|
35
|
+
8qAqdfV+4u6Huu1KzAuDQCheyEyISsLST37sU/irV3czV6BiFipWag1XiJciRT3A
|
36
|
+
wZqCfTNVHTdtsCbfdA1DsA3RdG2iEH3TOHzv1Rqzqh4=
|
36
37
|
-----END CERTIFICATE-----
|
37
|
-
date:
|
38
|
+
date: 2025-07-12 00:00:00.000000000 Z
|
38
39
|
dependencies:
|
39
40
|
- !ruby/object:Gem::Dependency
|
40
41
|
name: loggability
|
@@ -100,7 +101,6 @@ metadata:
|
|
100
101
|
changelog_uri: https://deveiate.org/code/pluggability/History_md.html
|
101
102
|
source_uri: https://hg.sr.ht/~ged/Pluggability/browse
|
102
103
|
bug_tracker_uri: https://todo.sr.ht/~ged/Pluggability/browse
|
103
|
-
post_install_message:
|
104
104
|
rdoc_options: []
|
105
105
|
require_paths:
|
106
106
|
- lib
|
@@ -115,8 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: '0'
|
117
117
|
requirements: []
|
118
|
-
rubygems_version: 3.
|
119
|
-
signing_key:
|
118
|
+
rubygems_version: 3.6.9
|
120
119
|
specification_version: 4
|
121
120
|
summary: Pluggability is a toolkit for creating plugins.
|
122
121
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|