pidgin 0.0.0.dev → 0.0.1.pre
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
- data/.gitignore +8 -0
- data/Gemfile.lock +57 -0
- data/lib/pidgin.rb +8 -0
- data/lib/pidgin/domain_specific_language.rb +59 -0
- data/lib/pidgin/object.rb +157 -0
- data/lib/pidgin/property.rb +18 -0
- data/lib/pidgin/version.rb +1 -1
- data/pidgin.gemspec +0 -3
- metadata +8 -19
- data/.DS_Store +0 -0
- data/lib/.DS_Store +0 -0
- data/lib/pidgin/.DS_Store +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 320f277f2080469c666e5eb6e63b16dc91acfef0
|
4
|
+
data.tar.gz: 2598a9b84457ccff4855b848f880fbfc288681ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ef34d7d512730de03039b5a6eda4d8ba324a4a26dc8233450a055421f7d5bf3da3b6260765fe785d7a660e873cb957a11640b246aa5c31782bec8f1a7dedc58
|
7
|
+
data.tar.gz: 26f74dcff76c6d96ac4c096b8b575a78014067608260bbc21bb999bc82903e03cad5e5361f0a8201d143cbb5ff03626ef82ed454271579afd316623326584697
|
data/.gitignore
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pidgin (0.0.0.dev)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
aruba (0.8.0)
|
10
|
+
childprocess (~> 0.5.6)
|
11
|
+
contracts (~> 0.9)
|
12
|
+
cucumber (>= 1.3.19)
|
13
|
+
rspec-expectations (>= 2.99)
|
14
|
+
builder (3.2.2)
|
15
|
+
childprocess (0.5.6)
|
16
|
+
ffi (~> 1.0, >= 1.0.11)
|
17
|
+
contracts (0.10)
|
18
|
+
cucumber (2.0.1)
|
19
|
+
builder (>= 2.1.2)
|
20
|
+
cucumber-core (~> 1.2.0)
|
21
|
+
diff-lcs (>= 1.1.3)
|
22
|
+
gherkin (~> 2.12)
|
23
|
+
multi_json (>= 1.7.5, < 2.0)
|
24
|
+
multi_test (>= 0.1.2)
|
25
|
+
cucumber-core (1.2.0)
|
26
|
+
gherkin (~> 2.12.0)
|
27
|
+
diff-lcs (1.2.5)
|
28
|
+
ffi (1.9.10)
|
29
|
+
gherkin (2.12.2)
|
30
|
+
multi_json (~> 1.3)
|
31
|
+
multi_json (1.11.2)
|
32
|
+
multi_test (0.1.2)
|
33
|
+
rspec (3.3.0)
|
34
|
+
rspec-core (~> 3.3.0)
|
35
|
+
rspec-expectations (~> 3.3.0)
|
36
|
+
rspec-mocks (~> 3.3.0)
|
37
|
+
rspec-core (3.3.1)
|
38
|
+
rspec-support (~> 3.3.0)
|
39
|
+
rspec-expectations (3.3.0)
|
40
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
41
|
+
rspec-support (~> 3.3.0)
|
42
|
+
rspec-mocks (3.3.1)
|
43
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
44
|
+
rspec-support (~> 3.3.0)
|
45
|
+
rspec-support (3.3.0)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
aruba
|
52
|
+
cucumber
|
53
|
+
pidgin!
|
54
|
+
rspec
|
55
|
+
|
56
|
+
BUNDLED WITH
|
57
|
+
1.10.5
|
data/lib/pidgin.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module Pidgin
|
2
|
+
module DomainSpecificLanguage
|
3
|
+
class Evaluator
|
4
|
+
def initialize(dsl)
|
5
|
+
@dsl = dsl
|
6
|
+
@objects = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(name, *args, &block)
|
10
|
+
objects = @dsl.class_variable_get(:@@objects)
|
11
|
+
collections = @dsl.class_variable_get(:@@collections)
|
12
|
+
if collections.any? { |collection| collection.object.name == name }
|
13
|
+
collection = (collections.select { |collection| collection.object.name == name }).first
|
14
|
+
object = collection.object
|
15
|
+
object_inst = Kernel.const_get("#{object.type}::DSL").eval(args.first, &block)
|
16
|
+
@objects[collection.name] ||= []
|
17
|
+
@objects[collection.name] << object_inst
|
18
|
+
elsif (objects.any? { |object| object.name == name })
|
19
|
+
object = (objects.select { |object| object.name == name }).first
|
20
|
+
object_inst = Kernel.const_get("#{object.type}::DSL").eval(args.first, &block)
|
21
|
+
raise "Tried to redefine `#{object.name}'!" if @objects.include? object.name
|
22
|
+
@objects[object.name] = object_inst
|
23
|
+
else
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module ClassMethods
|
30
|
+
def object(name, type)
|
31
|
+
dsl = Kernel.const_get(self.name)
|
32
|
+
object = OpenStruct.new({:name => name, :type => type})
|
33
|
+
dsl.class_variable_get(:@@objects) << object
|
34
|
+
object
|
35
|
+
end
|
36
|
+
|
37
|
+
def collection(name, type, opts={})
|
38
|
+
plural = opts[:plural] || "#{name}s"
|
39
|
+
dsl = Kernel.const_get(self.name)
|
40
|
+
collection = OpenStruct.new({:name => plural, :object => OpenStruct.new({:name => name, :type => type})})
|
41
|
+
dsl.class_variable_get(:@@collections) << collection
|
42
|
+
collection
|
43
|
+
end
|
44
|
+
|
45
|
+
def eval(code)
|
46
|
+
dsl = Kernel.const_get(self.name)
|
47
|
+
evaluator = Evaluator.new(dsl)
|
48
|
+
evaluator.instance_eval(code)
|
49
|
+
evaluator.instance_variable_get(:@objects).freeze
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.included(klass)
|
54
|
+
klass.class_variable_set(:@@objects, [])
|
55
|
+
klass.class_variable_set(:@@collections, [])
|
56
|
+
klass.extend(ClassMethods)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module Pidgin
|
2
|
+
module Object
|
3
|
+
module DomainSpecificLanguage
|
4
|
+
module ClassMethods
|
5
|
+
def eval(inlined_props={}, &block)
|
6
|
+
inlined_props ||= {}
|
7
|
+
object_klass = Kernel.const_get(self.name.split('::')[0..-2].join('::'))
|
8
|
+
puts "Pidgin::Object::DomainSpecificLanguage.eval for #{object_klass}"
|
9
|
+
|
10
|
+
# Handle inlined properties, adjusting |inlined_props| as we go along.
|
11
|
+
instances_of_props = {}
|
12
|
+
allowable_inlined_props = object_klass.class_variable_get(:@@properties)
|
13
|
+
.select { |prop| prop.inline? }
|
14
|
+
allowable_inlined_props.each do |allowable_inlined_prop|
|
15
|
+
instances_of_prop = inlined_props.select { |name, _| name == allowable_inlined_prop.name }
|
16
|
+
specified_at_least_once = instances_of_prop.length > 0
|
17
|
+
specified_more_than_once = instances_of_prop.length > 1
|
18
|
+
if specified_more_than_once
|
19
|
+
# Freak out, because there's no 'good' way to handle the same inlined
|
20
|
+
# propeter being specified twice. Note however, that this shouldn't
|
21
|
+
# occur, at least if |inlined_props| is a hash.
|
22
|
+
raise ArgumentError.new("The inlined property `#{allowable_inlined_prop.name}' was specified more than once?!")
|
23
|
+
elsif specified_at_least_once
|
24
|
+
instance_of_prop = instances_of_prop.first
|
25
|
+
instances_of_sub_props = {}
|
26
|
+
# TODO(mtwilliams): Refactor out the commonality between these.
|
27
|
+
allowable_inlined_prop.sub_properties.each do |allowable_sub_prop|
|
28
|
+
instances_of_sub_prop = inlined_props.select { |name, _| name == allowable_sub_prop.name }
|
29
|
+
specified_at_least_once = instances_of_sub_prop.length > 0
|
30
|
+
specified_more_than_once = instances_of_sub_prop.length > 1
|
31
|
+
if specified_more_than_once
|
32
|
+
# Similar deal.
|
33
|
+
raise ArgumentError.new("The inlined sub-property `#{allowable_sub_prop.name}' was specified more than once?!")
|
34
|
+
elsif specified_at_least_once
|
35
|
+
instance_of_sub_prop = instances_of_sub_prop.first
|
36
|
+
sub_prop = allowable_sub_prop.type.new(instance_of_sub_prop[1])
|
37
|
+
instances_of_sub_props.merge! Hash[allowable_sub_prop.name, sub_prop]
|
38
|
+
end
|
39
|
+
inlined_props.reject! { |name, _| name == allowable_sub_prop.name }
|
40
|
+
end
|
41
|
+
# TODO(mtwilliams): Refactor?
|
42
|
+
case allowable_inlined_prop.type.name.to_sym
|
43
|
+
when :nil
|
44
|
+
# TODO(mtwilliams): Freak out, proper.
|
45
|
+
raise "..."
|
46
|
+
when :TrueClass
|
47
|
+
instances_of_props = instances_of_props.merge! Hash[allowable_inlined_prop.name, !!instance_of_prop[1]]
|
48
|
+
when :FalseClass
|
49
|
+
instances_of_props = instances_of_props.merge! Hash[allowable_inlined_prop.name, !!!instance_of_prop[1]]
|
50
|
+
else
|
51
|
+
prop = allowable_inlined_prop.type.new(instance_of_prop[1], instances_of_sub_props)
|
52
|
+
instances_of_props = instances_of_props.merge! Hash[allowable_inlined_prop.name, prop]
|
53
|
+
end
|
54
|
+
inlined_props.reject! { |name, _| name == allowable_inlined_prop.name }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# If any arguments remain, then the user has done something wrong.
|
59
|
+
raise ArgumentError.new("Unknown properties were supplied inline.") unless inlined_props.empty?
|
60
|
+
|
61
|
+
# Use the builder pattern to create an instance of the object, however
|
62
|
+
# proxy all of the DSL user's calls so they don't stomp on internals.
|
63
|
+
object_builder = ((Class.new do
|
64
|
+
def initialize(klass, properties)
|
65
|
+
@klass = klass
|
66
|
+
@properties = properties
|
67
|
+
@sub_objects = {}
|
68
|
+
end
|
69
|
+
|
70
|
+
def build
|
71
|
+
object_inst = @klass.new
|
72
|
+
@sub_objects.each { |name, sub_object_inst| object_inst.instance_variable_set("@#{name}".to_sym, sub_object_inst) }
|
73
|
+
@properties.each { |name, property| object_inst.instance_variable_set("@#{name}".to_sym, property) }
|
74
|
+
object_inst.freeze
|
75
|
+
end
|
76
|
+
end).new(object_klass, instances_of_props))
|
77
|
+
|
78
|
+
(Class.new do
|
79
|
+
def initialize(klass, builder)
|
80
|
+
@klass = klass
|
81
|
+
@builder = builder
|
82
|
+
end
|
83
|
+
|
84
|
+
def method_missing(name, *args, &block)
|
85
|
+
objects = @klass.class_variable_get(:@@objects)
|
86
|
+
collections = @klass.class_variable_get(:@@collections)
|
87
|
+
properties = @klass.class_variable_get(:@@properties)
|
88
|
+
if objects.any? { |object| object.name == name }
|
89
|
+
object = (objects.select { |object| object.name == name }).first
|
90
|
+
object_inst = Kernel.const_get("#{object.type}::DSL").eval(args.first, &block)
|
91
|
+
raise "Tried to redefine `#{object.name}'!" if @builder.instance_variable_get(:@sub_objects).include? object.name
|
92
|
+
@builder.instance_variable_get(:@sub_objects)[object.name] = object_inst
|
93
|
+
object_inst
|
94
|
+
elsif collections.any? { |collection| collection.object.name == name }
|
95
|
+
collection = (collections.select { |collection| collection.object.name == name }).first
|
96
|
+
object = collection.object
|
97
|
+
object_inst = Kernel.const_get("#{object.type}::DSL").eval(args.first, &block)
|
98
|
+
@builder.instance_variable_get(:@sub_objects)[collection.name] ||= []
|
99
|
+
@builder.instance_variable_get(:@sub_objects)[collection.name] << object_inst
|
100
|
+
object_inst
|
101
|
+
elsif properties.any? { |property| property.name == name }
|
102
|
+
property = (properties.select{ |prop| prop.name == name }).first
|
103
|
+
raise ArgumentError.new("Excepted sub-properties as a second argument!") if (args.length > 1) && !(args[1].is_a? Hash)
|
104
|
+
property_inst = property.type.new(args[0], args[1])
|
105
|
+
@builder.instance_variable_get(:@properties).merge!({property.name => property_inst})
|
106
|
+
property_inst
|
107
|
+
else
|
108
|
+
super
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end).new(object_klass, object_builder).instance_eval(&block)
|
112
|
+
|
113
|
+
object = object_builder.build
|
114
|
+
return object
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.included(klass)
|
119
|
+
klass.extend(ClassMethods)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
module ClassMethods
|
124
|
+
def object(name, type)
|
125
|
+
object_klass = Kernel.const_get(self.name)
|
126
|
+
object = OpenStruct.new({:name => name, :type => type})
|
127
|
+
object_klass.class_variable_get(:@@objects) << object
|
128
|
+
object
|
129
|
+
end
|
130
|
+
|
131
|
+
def collection(name, type, opts={})
|
132
|
+
plural = opts[:plural] || "#{name}s"
|
133
|
+
object_klass = Kernel.const_get(self.name)
|
134
|
+
collection = OpenStruct.new({:name => plural, :object => OpenStruct.new({:name => name, :type => type})})
|
135
|
+
object_klass.class_variable_get(:@@collections) << collection
|
136
|
+
collection
|
137
|
+
end
|
138
|
+
|
139
|
+
def property(name, type, opts={})
|
140
|
+
object_klass = Kernel.const_get(self.name)
|
141
|
+
property = Property.new(name, type, opts)
|
142
|
+
object_klass.class_variable_get(:@@properties) << property
|
143
|
+
property
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.included(klass)
|
148
|
+
klass.class_variable_set(:@@objects, [])
|
149
|
+
klass.class_variable_set(:@@collections, [])
|
150
|
+
klass.class_variable_set(:@@properties, [])
|
151
|
+
klass.extend(ClassMethods)
|
152
|
+
klass.const_set(:DSL, Class.new do
|
153
|
+
include Pidgin::Object::DomainSpecificLanguage
|
154
|
+
end)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Pidgin
|
2
|
+
class Property
|
3
|
+
def initialize(name, type, opts={})
|
4
|
+
@name = name
|
5
|
+
@type = type
|
6
|
+
@inline = opts[:inline] || false
|
7
|
+
@sub_properties = []
|
8
|
+
(opts[:allow] || {}).each do |sub_prop_name, sub_prop_type|
|
9
|
+
@sub_properties << Property.new(sub_prop_name, sub_prop_type)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def name; @name; end
|
14
|
+
def type; @type; end
|
15
|
+
def inline?; @inline; end
|
16
|
+
def sub_properties; @sub_properties; end
|
17
|
+
end
|
18
|
+
end
|
data/lib/pidgin/version.rb
CHANGED
data/pidgin.gemspec
CHANGED
@@ -16,11 +16,8 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.files = `git ls-files`.split("\n")
|
17
17
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
-
# TODO(mtwilliams): Handle this gracefuly in `bin/pidgin'.
|
20
19
|
s.require_paths = %w(lib)
|
21
20
|
|
22
|
-
s.add_dependency 'docile'
|
23
|
-
|
24
21
|
s.add_development_dependency 'rspec'
|
25
22
|
s.add_development_dependency 'cucumber'
|
26
23
|
s.add_development_dependency 'aruba'
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pidgin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: docile
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: rspec
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,11 +58,14 @@ executables: []
|
|
72
58
|
extensions: []
|
73
59
|
extra_rdoc_files: []
|
74
60
|
files:
|
75
|
-
- ".
|
61
|
+
- ".gitignore"
|
76
62
|
- Gemfile
|
63
|
+
- Gemfile.lock
|
77
64
|
- README.md
|
78
|
-
- lib
|
79
|
-
- lib/pidgin
|
65
|
+
- lib/pidgin.rb
|
66
|
+
- lib/pidgin/domain_specific_language.rb
|
67
|
+
- lib/pidgin/object.rb
|
68
|
+
- lib/pidgin/property.rb
|
80
69
|
- lib/pidgin/version.rb
|
81
70
|
- pidgin.gemspec
|
82
71
|
- pidgin.sublime-project
|
data/.DS_Store
DELETED
Binary file
|
data/lib/.DS_Store
DELETED
Binary file
|
data/lib/pidgin/.DS_Store
DELETED
Binary file
|