dry-auto_inject 0.6.0 → 0.9.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.
@@ -5,7 +5,7 @@ module Dry
5
5
  DuplicateDependencyError = Class.new(StandardError)
6
6
  DependencyNameInvalid = Class.new(StandardError)
7
7
 
8
- VALID_NAME = /([a-z_][a-zA-Z_0-9]*)$/
8
+ VALID_NAME = /([a-z_][a-zA-Z_0-9]*)$/.freeze
9
9
 
10
10
  class DependencyMap
11
11
  def initialize(*dependencies)
@@ -29,7 +29,7 @@ module Dry
29
29
  end
30
30
 
31
31
  def names
32
- @name ||= @map.keys
32
+ @names ||= @map.keys
33
33
  end
34
34
 
35
35
  def to_h
@@ -41,13 +41,18 @@ module Dry
41
41
 
42
42
  def name_for(identifier)
43
43
  matched = VALID_NAME.match(identifier.to_s)
44
- raise DependencyNameInvalid, "name +#{identifier}+ is not a valid Ruby identifier" unless matched
44
+ unless matched
45
+ raise DependencyNameInvalid,
46
+ "name +#{identifier}+ is not a valid Ruby identifier"
47
+ end
48
+
45
49
  matched[0]
46
50
  end
47
51
 
48
52
  def add_dependency(name, identifier)
49
53
  name = name.to_sym
50
54
  raise DuplicateDependencyError, "name +#{name}+ is already used" if @map.key?(name)
55
+
51
56
  @map[name] = identifier
52
57
  end
53
58
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/auto_inject/strategies'
3
+ require "dry/auto_inject/strategies"
4
4
 
5
5
  module Dry
6
6
  module AutoInject
@@ -14,6 +14,8 @@ module Dry
14
14
  # @api private
15
15
  attr_reader :builder
16
16
 
17
+ define_method(:respond_to?, ::Kernel.instance_method(:respond_to?))
18
+
17
19
  # @api private
18
20
  def initialize(container, strategy, builder:)
19
21
  @container = container
@@ -25,13 +27,13 @@ module Dry
25
27
  strategy.new(container, *dependency_names)
26
28
  end
27
29
 
28
- def respond_to?(name, include_private = false)
29
- Injector.instance_methods.include?(name) || builder.respond_to?(name)
30
+ def respond_to_missing?(name, _include_private = false)
31
+ builder.respond_to?(name)
30
32
  end
31
33
 
32
34
  private
33
35
 
34
- def method_missing(name, *args, &block)
36
+ def method_missing(name, *_args)
35
37
  builder.__send__(name)
36
38
  end
37
39
  end
@@ -1,47 +1,25 @@
1
- require 'set'
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
2
4
 
3
5
  module Dry
4
6
  module AutoInject
5
7
  # @api private
6
8
  class MethodParameters
7
- PASS_THROUGH = [[:rest]]
8
-
9
- if RUBY_VERSION >= '2.4.4.' && !defined? JRUBY_VERSION
10
- def self.of(obj, name)
11
- Enumerator.new do |y|
12
- begin
13
- method = obj.instance_method(name)
14
- rescue NameError
15
- end
16
-
17
- loop do
18
- break if method.nil?
19
-
20
- y << MethodParameters.new(method.parameters)
21
- method = method.super_method
22
- end
9
+ PASS_THROUGH = [[%i[rest]], [%i[rest], %i[keyrest]]].freeze
10
+
11
+ def self.of(obj, name)
12
+ Enumerator.new do |y|
13
+ begin
14
+ method = obj.instance_method(name)
15
+ rescue ::NameError # rubocop: disable Lint/SuppressedException
23
16
  end
24
- end
25
- else
26
- # see https://bugs.ruby-lang.org/issues/13973
27
- def self.of(obj, name)
28
- Enumerator.new do |y|
29
- ancestors = obj.ancestors
30
-
31
- loop do
32
- klass = ancestors.shift
33
- break if klass.nil?
34
-
35
- begin
36
- method = klass.instance_method(name)
37
-
38
- next unless method.owner.equal?(klass)
39
- rescue NameError
40
- next
41
- end
42
-
43
- y << MethodParameters.new(method.parameters)
44
- end
17
+
18
+ loop do
19
+ break if method.nil?
20
+
21
+ y << MethodParameters.new(method.parameters)
22
+ method = method.super_method
45
23
  end
46
24
  end
47
25
  end
@@ -54,11 +32,13 @@ module Dry
54
32
 
55
33
  def splat?
56
34
  return @splat if defined? @splat
35
+
57
36
  @splat = parameters.any? { |type, _| type == :rest }
58
37
  end
59
38
 
60
39
  def sequential_arguments?
61
40
  return @sequential_arguments if defined? @sequential_arguments
41
+
62
42
  @sequential_arguments = parameters.any? { |type, _|
63
43
  type == :req || type == :opt
64
44
  }
@@ -83,7 +63,7 @@ module Dry
83
63
  end
84
64
 
85
65
  def pass_through?
86
- parameters.eql?(PASS_THROUGH)
66
+ PASS_THROUGH.include?(parameters)
87
67
  end
88
68
 
89
69
  EMPTY = new([])
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/auto_inject/strategies/constructor'
4
- require 'dry/auto_inject/method_parameters'
3
+ require "dry/auto_inject/strategies/constructor"
4
+ require "dry/auto_inject/method_parameters"
5
5
 
6
6
  module Dry
7
7
  module AutoInject
@@ -17,7 +17,7 @@ module Dry
17
17
  args[i] || container[identifier]
18
18
  }
19
19
 
20
- super(*deps, *args[deps.size..-1])
20
+ super(*deps, *args[deps.size..])
21
21
  end
22
22
  end
23
23
  end
@@ -36,28 +36,35 @@ module Dry
36
36
  end
37
37
 
38
38
  def define_initialize_with_params
39
- initialize_args = dependency_map.names.join(', ')
39
+ initialize_args = dependency_map.names.join(", ")
40
+
41
+ assignment = dependency_map.names.map { "@#{_1} = #{_1}" }.join("\n")
40
42
 
41
43
  instance_mod.class_eval <<-RUBY, __FILE__, __LINE__ + 1
42
- def initialize(#{initialize_args})
43
- #{dependency_map.names.map { |name| "@#{name} = #{name}" }.join("\n")}
44
- super()
45
- end
44
+ def initialize(#{initialize_args}) # def initialize(dep)
45
+ #{assignment} # @dep = dep
46
+ super() # super()
47
+ end # end
46
48
  RUBY
47
49
  end
48
50
 
49
51
  def define_initialize_with_splat(super_parameters)
50
52
  super_pass = if super_parameters.splat?
51
- '*args'
52
- else
53
- "*args.take(#{super_parameters.length})"
53
+ "*args"
54
+ else
55
+ "*args.take(#{super_parameters.length})"
56
+ end
57
+
58
+ assignments = dependency_map.names.map.with_index do |name, idx|
59
+ "@#{name} = args[#{idx}]"
54
60
  end
61
+ body = assignments.join("\n")
55
62
 
56
63
  instance_mod.class_eval <<-RUBY, __FILE__, __LINE__ + 1
57
- def initialize(*args)
58
- #{dependency_map.names.map.with_index { |name, i| "@#{name} = args[#{i}]" }.join("\n")}
59
- super(#{super_pass})
60
- end
64
+ def initialize(*args) # def initialize(*args)
65
+ #{body} # @dep = args[0]
66
+ super(#{super_pass}) # super(*args)
67
+ end # end
61
68
  RUBY
62
69
  end
63
70
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/auto_inject/dependency_map'
3
+ require "dry/auto_inject/dependency_map"
4
4
 
5
5
  module Dry
6
6
  module AutoInject
@@ -15,6 +15,7 @@ module Dry
15
15
  attr_reader :class_mod
16
16
 
17
17
  def initialize(container, *dependency_names)
18
+ super()
18
19
  @container = container
19
20
  @dependency_map = DependencyMap.new(*dependency_names)
20
21
  @instance_mod = InstanceMethods.new
@@ -37,8 +38,9 @@ module Dry
37
38
  private
38
39
 
39
40
  def define_readers
41
+ readers = dependency_map.names.map { ":#{_1}" }
40
42
  instance_mod.class_eval <<-RUBY, __FILE__, __LINE__ + 1
41
- attr_reader #{dependency_map.names.map { |name| ":#{name}" }.join(', ')}
43
+ attr_reader #{readers.join(", ")} # attr_reader :dep1, :dep2
42
44
  RUBY
43
45
  self
44
46
  end
@@ -47,7 +49,7 @@ module Dry
47
49
  raise NotImplementedError, "must be implemented by a subclass"
48
50
  end
49
51
 
50
- def define_initialize(klass)
52
+ def define_initialize(_klass)
51
53
  raise NotImplementedError, "must be implemented by a subclass"
52
54
  end
53
55
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/auto_inject/strategies/constructor'
4
- require 'dry/auto_inject/method_parameters'
3
+ require "dry/auto_inject/strategies/constructor"
4
+ require "dry/auto_inject/method_parameters"
5
5
 
6
6
  module Dry
7
7
  module AutoInject
@@ -24,13 +24,23 @@ module Dry
24
24
 
25
25
  def define_initialize(klass)
26
26
  super_params = MethodParameters.of(klass, :initialize).first
27
- super_pass = super_params.empty? ? '' : 'options'
27
+ super_pass = super_params.empty? ? "" : "options"
28
+ assignments = dependency_map.names.map do |name|
29
+ <<~RUBY
30
+ unless !options.key?(:#{name}) && instance_variable_defined?(:'@#{name}')
31
+ @#{name} = options[:#{name}]
32
+ end
33
+ RUBY
34
+ end
35
+ body = assignments.join("\n")
28
36
 
29
37
  instance_mod.class_eval <<-RUBY, __FILE__, __LINE__ + 1
30
- def initialize(options)
31
- #{dependency_map.names.map { |name| "@#{name} = options[:#{name}] unless !options.key?(#{name}) && instance_variable_defined?(:'@#{name}')" }.join("\n")}
32
- super(#{super_pass})
33
- end
38
+ def initialize(options) # def initialize(options)
39
+ # unless !options.key?(:dep) && instance_variable_defined?(:@dep)
40
+ #{body} # @dep = options[:dep]
41
+ # end
42
+ super(#{super_pass}) # super(options)
43
+ end # end
34
44
  RUBY
35
45
  end
36
46
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/auto_inject/strategies/constructor'
4
- require 'dry/auto_inject/method_parameters'
3
+ require "dry/auto_inject/strategies/constructor"
4
+ require "dry/auto_inject/method_parameters"
5
5
 
6
6
  module Dry
7
7
  module AutoInject
@@ -14,19 +14,20 @@ module Dry
14
14
  class_mod.class_exec(container, dependency_map) do |container, dependency_map|
15
15
  map = dependency_map.to_h
16
16
 
17
- define_method :new do |*args, **kwargs|
17
+ define_method :new do |*args, **kwargs, &block|
18
18
  map.each do |name, identifier|
19
- kwargs[name] ||= container[identifier]
19
+ kwargs[name] = container[identifier] unless kwargs.key?(name)
20
20
  end
21
21
 
22
- super(*args, **kwargs)
22
+ super(*args, **kwargs, &block)
23
23
  end
24
24
  end
25
25
  end
26
26
 
27
27
  def define_initialize(klass)
28
28
  super_parameters = MethodParameters.of(klass, :initialize).each do |ps|
29
- # Look upwards past `def foo(*)` methods until we get an explicit list of parameters
29
+ # Look upwards past `def foo(*)` and `def foo(...)` methods
30
+ # until we get an explicit list of parameters
30
31
  break ps unless ps.pass_through?
31
32
  end
32
33
 
@@ -44,15 +45,15 @@ module Dry
44
45
  slice_kwargs = method(:slice_kwargs)
45
46
 
46
47
  instance_mod.class_exec do
47
- define_method :initialize do |**kwargs|
48
+ define_method :initialize do |**kwargs, &block|
48
49
  assign_dependencies.(kwargs, self)
49
50
 
50
51
  super_kwargs = slice_kwargs.(kwargs, super_parameters)
51
52
 
52
53
  if super_kwargs.any?
53
- super(super_kwargs)
54
+ super(**super_kwargs, &block)
54
55
  else
55
- super()
56
+ super(&block)
56
57
  end
57
58
  end
58
59
  end
@@ -63,18 +64,18 @@ module Dry
63
64
  slice_kwargs = method(:slice_kwargs)
64
65
 
65
66
  instance_mod.class_exec do
66
- define_method :initialize do |*args, **kwargs|
67
+ define_method :initialize do |*args, **kwargs, &block|
67
68
  assign_dependencies.(kwargs, self)
68
69
 
69
70
  if super_parameters.splat?
70
- super(*args, kwargs)
71
+ super(*args, **kwargs, &block)
71
72
  else
72
73
  super_kwargs = slice_kwargs.(kwargs, super_parameters)
73
74
 
74
75
  if super_kwargs.any?
75
- super(*args, super_kwargs)
76
+ super(*args, **super_kwargs, &block)
76
77
  else
77
- super(*args)
78
+ super(*args, &block)
78
79
  end
79
80
  end
80
81
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry-container'
3
+ require "dry-container"
4
4
 
5
5
  module Dry
6
6
  module AutoInject
@@ -16,6 +16,6 @@ module Dry
16
16
  end
17
17
  end
18
18
 
19
- require 'dry/auto_inject/strategies/args'
20
- require 'dry/auto_inject/strategies/hash'
21
- require 'dry/auto_inject/strategies/kwargs'
19
+ require "dry/auto_inject/strategies/args"
20
+ require "dry/auto_inject/strategies/hash"
21
+ require "dry/auto_inject/strategies/kwargs"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Dry
4
4
  module AutoInject
5
- VERSION = '0.6.0'
5
+ VERSION = "0.9.0"
6
6
  end
7
7
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/auto_inject/builder'
3
+ require "dry/auto_inject/builder"
4
4
 
5
5
  module Dry
6
6
  # Configure an auto-injection module
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/auto_inject'
3
+ require "dry/auto_inject"
metadata CHANGED
@@ -1,92 +1,81 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-auto_inject
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
- autorequire:
9
- bindir: exe
8
+ autorequire:
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-29 00:00:00.000000000 Z
11
+ date: 2022-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
+ name: dry-container
14
15
  requirement: !ruby/object:Gem::Requirement
15
16
  requirements:
16
17
  - - ">="
17
18
  - !ruby/object:Gem::Version
18
19
  version: 0.3.4
19
- name: dry-container
20
- prerelease: false
21
20
  type: :runtime
21
+ prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.3.4
27
27
  - !ruby/object:Gem::Dependency
28
+ name: bundler
28
29
  requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
31
  - - ">="
31
32
  - !ruby/object:Gem::Version
32
33
  version: '0'
33
- name: bundler
34
- prerelease: false
35
34
  type: :development
35
+ prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
+ name: rake
42
43
  requirement: !ruby/object:Gem::Requirement
43
44
  requirements:
44
45
  - - ">="
45
46
  - !ruby/object:Gem::Version
46
47
  version: '0'
47
- name: rake
48
- prerelease: false
49
48
  type: :development
49
+ prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
+ name: rspec
56
57
  requirement: !ruby/object:Gem::Requirement
57
58
  requirements:
58
- - - "~>"
59
+ - - ">="
59
60
  - !ruby/object:Gem::Version
60
- version: '3.8'
61
- name: rspec
62
- prerelease: false
61
+ version: '0'
63
62
  type: :development
63
+ prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '3.8'
69
- description:
68
+ version: '0'
69
+ description: Container-agnostic automatic constructor injection
70
70
  email:
71
71
  - piotr.solnica@gmail.com
72
72
  executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
- - ".codeclimate.yml"
77
- - ".gitignore"
78
- - ".rspec"
79
- - ".rubocop.yml"
80
- - ".rubocop_todo.yml"
81
- - ".travis.yml"
82
76
  - CHANGELOG.md
83
- - CONTRIBUTING.md
84
- - Gemfile
85
77
  - LICENSE
86
78
  - README.md
87
- - Rakefile
88
- - bin/console
89
- - bin/setup
90
79
  - dry-auto_inject.gemspec
91
80
  - lib/dry-auto_inject.rb
92
81
  - lib/dry/auto_inject.rb
@@ -100,12 +89,15 @@ files:
100
89
  - lib/dry/auto_inject/strategies/hash.rb
101
90
  - lib/dry/auto_inject/strategies/kwargs.rb
102
91
  - lib/dry/auto_inject/version.rb
103
- - rakelib/rubocop.rake
104
- homepage: https://github.com/dryrb/dry-auto_inject
92
+ homepage: https://dry-rb.org/gems/dry-auto_inject
105
93
  licenses:
106
94
  - MIT
107
- metadata: {}
108
- post_install_message:
95
+ metadata:
96
+ allowed_push_host: https://rubygems.org
97
+ changelog_uri: https://github.com/dry-rb/dry-auto_inject/blob/master/CHANGELOG.md
98
+ source_code_uri: https://github.com/dry-rb/dry-auto_inject
99
+ bug_tracker_uri: https://github.com/dry-rb/dry-auto_inject/issues
100
+ post_install_message:
109
101
  rdoc_options: []
110
102
  require_paths:
111
103
  - lib
@@ -113,16 +105,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
105
  requirements:
114
106
  - - ">="
115
107
  - !ruby/object:Gem::Version
116
- version: 2.3.0
108
+ version: 2.7.0
117
109
  required_rubygems_version: !ruby/object:Gem::Requirement
118
110
  requirements:
119
111
  - - ">="
120
112
  - !ruby/object:Gem::Version
121
113
  version: '0'
122
114
  requirements: []
123
- rubyforge_project:
124
- rubygems_version: 2.7.6
125
- signing_key:
115
+ rubygems_version: 3.1.6
116
+ signing_key:
126
117
  specification_version: 4
127
118
  summary: Container-agnostic automatic constructor injection
128
119
  test_files: []
data/.codeclimate.yml DELETED
@@ -1,6 +0,0 @@
1
- engines:
2
- rubocop:
3
- enabled: true
4
- ratings:
5
- paths:
6
- - lib/**
data/.gitignore DELETED
@@ -1,10 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /vendor/
6
- /coverage/
7
- /doc/
8
- /pkg/
9
- /spec/reports/
10
- /tmp/
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --require spec_helper
data/.rubocop.yml DELETED
@@ -1,19 +0,0 @@
1
- # Generated by `rubocop --auto-gen-config`
2
- inherit_from: .rubocop_todo.yml
3
-
4
- Metrics/LineLength:
5
- Max: 110
6
-
7
- Lint/HandleExceptions:
8
- Exclude:
9
- - rakelib/*.rake
10
-
11
- Style/LambdaCall:
12
- EnforcedStyle: braces
13
-
14
- Style/Documentation:
15
- Enabled: false
16
-
17
- Style/FileName:
18
- Exclude:
19
- - lib/dry-pipeline.rb
data/.rubocop_todo.yml DELETED
@@ -1,6 +0,0 @@
1
- # This configuration was generated by `rubocop --auto-gen-config`
2
- # on 2015-08-19 22:11:28 +0100 using RuboCop version 0.32.0.
3
- # The point is for the user to remove these configuration records
4
- # one by one as the offenses are removed from the code base.
5
- # Note that changes in the inspected code, or installation of new
6
- # versions of RuboCop, may require this file to be generated again.
data/.travis.yml DELETED
@@ -1,23 +0,0 @@
1
- language: ruby
2
- cache: bundler
3
- bundler_args: --without tools
4
- script:
5
- - bundle exec rake
6
- after_success:
7
- - '[ -d coverage ] && bundle exec codeclimate-test-reporter'
8
- rvm:
9
- - 2.5.3
10
- - 2.4.5
11
- - 2.3.8
12
- - jruby-9.2.4.1
13
- env:
14
- global:
15
- - COVERAGE=true
16
- notifications:
17
- email: false
18
- webhooks:
19
- urls:
20
- - https://webhooks.gitter.im/e/19098b4253a72c9796db
21
- on_success: change # options: [always|never|change] default: always
22
- on_failure: always # options: [always|never|change] default: always
23
- on_start: false # default: false
data/CONTRIBUTING.md DELETED
@@ -1,29 +0,0 @@
1
- # Issue Guidelines
2
-
3
- ## Reporting bugs
4
-
5
- If you found a bug, report an issue and describe what's the expected behavior versus what actually happens. If the bug causes a crash, attach a full backtrace. If possible, a reproduction script showing the problem is highly appreciated.
6
-
7
- ## Reporting feature requests
8
-
9
- Report a feature request **only after discussing it first on [discuss.dry-rb.org](https://discuss.dry-rb.org)** where it was accepted. Please provide a concise description of the feature, don't link to a discussion thread, and instead summarize what was discussed.
10
-
11
- ## Reporting questions, support requests, ideas, concerns etc.
12
-
13
- **PLEASE DON'T** - use [discuss.dry-rb.org](http://discuss.dry-rb.org) instead.
14
-
15
- # Pull Request Guidelines
16
-
17
- A Pull Request will only be accepted if it addresses a specific issue that was reported previously, or fixes typos, mistakes in documentation etc.
18
-
19
- Other requirements:
20
-
21
- 1) Do not open a pull request if you can't provide tests along with it. If you have problems writing tests, ask for help in the related issue.
22
- 2) Follow the style conventions of the surrounding code. In most cases, this is standard ruby style.
23
- 3) Add API documentation if it's a new feature
24
- 4) Update API documentation if it changes an existing feature
25
- 5) Bonus points for sending a PR to [github.com/dry-rb/dry-rb.org](github.com/dry-rb/dry-rb.org) which updates user documentation and guides
26
-
27
- # Asking for help
28
-
29
- If these guidelines aren't helpful, and you're stuck, please post a message on [discuss.dry-rb.org](https://discuss.dry-rb.org).