pincushion 0.0.1 → 0.1.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
- data/lib/pincushion.rb +37 -9
- data/lib/pincushion/plugins.rb +20 -0
- data/lib/pincushion/plugins/csv_serializer.rb +19 -2
- data/lib/pincushion/plugins/json_serializer.rb +11 -3
- data/lib/pincushion/version.rb +1 -3
- data/spec/pincushion_spec.rb +95 -0
- data/spec/spec_helper.rb +4 -0
- metadata +40 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8eab64e433918cb3f0881c57abb7d09a4dd1bfac
|
4
|
+
data.tar.gz: 4ca030d28f2cf4ef8b270d9a47e116cdf4a1e314
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb77a2fd89d401c263b68ab334ee3a5eeeefa816d9578be94bb537b800c7d7abaad7169c30dbb7ce44a8dfd1637699c9d9d895e46324f0a851396382c29f6a61
|
7
|
+
data.tar.gz: 1b6df11775ecd620373e87767ae3e1c927541a0d9d0d145c0b56262ff4e2d357e09b151102563bf61866fdaaa4da8580a2e7d689526ec3ec40fc622f47e44c71
|
data/lib/pincushion.rb
CHANGED
@@ -2,18 +2,42 @@ require 'set'
|
|
2
2
|
require 'pincushion/plugins'
|
3
3
|
|
4
4
|
module Pincushion
|
5
|
+
def self.from_rows(rows)
|
6
|
+
Module.new.module_eval do
|
7
|
+
include Pincushion
|
8
|
+
|
9
|
+
predicates = rows
|
10
|
+
.reduce(Set.new) { |a, e| a.merge(e.keys) }
|
11
|
+
.delete(:identifier)
|
12
|
+
predicates(*predicates)
|
13
|
+
|
14
|
+
rows.each do |row|
|
15
|
+
row = row.dup
|
16
|
+
identifier = row.delete(:identifier)
|
17
|
+
true_predicates = row.each_pair.select { |_, v| v }.map { |k, _| k }
|
18
|
+
that_is(*true_predicates).named(identifier)
|
19
|
+
end
|
20
|
+
|
21
|
+
self
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.validate(mod, preds)
|
26
|
+
violations = Set.new(preds) - mod.predicates
|
27
|
+
return if violations.empty?
|
28
|
+
fail MissingPredicateError,
|
29
|
+
"Tried to set a value for unregistered predicate(s): "\
|
30
|
+
"#{violations.inspect}"
|
31
|
+
end
|
32
|
+
|
5
33
|
module RootModuleMethods
|
6
34
|
include Plugins
|
7
35
|
|
8
36
|
attr_reader :identifiers
|
9
37
|
|
10
|
-
def
|
11
|
-
identifiers.map
|
12
|
-
|
13
|
-
|
14
|
-
def all_identifiers_predicates_rows
|
15
|
-
identifiers.flat_map do |id, cls|
|
16
|
-
cls.new(id).all_predicates_hash.map { |k, v| [id, k, v] }
|
38
|
+
def rows
|
39
|
+
identifiers.map do |id, cls|
|
40
|
+
{ identifier: id }.merge(cls.new(id).all_predicates_hash)
|
17
41
|
end
|
18
42
|
end
|
19
43
|
|
@@ -26,9 +50,9 @@ module Pincushion
|
|
26
50
|
end
|
27
51
|
|
28
52
|
def predicates(*preds)
|
29
|
-
return @predicates if preds.empty?
|
53
|
+
return (@predicates || Set.new) if preds.empty?
|
30
54
|
fail "Predicates can't be changed after initialization" if @predicates
|
31
|
-
@predicates = Set.new
|
55
|
+
@predicates = Set.new(preds)
|
32
56
|
is_not(*@predicates)
|
33
57
|
@predicates.each do |predicate|
|
34
58
|
alias_method(:"is_#{predicate}?", :"#{predicate}?")
|
@@ -53,11 +77,13 @@ module Pincushion
|
|
53
77
|
end
|
54
78
|
|
55
79
|
def is(*preds)
|
80
|
+
Pincushion.validate(predicate_pincushion_root, preds)
|
56
81
|
preds.each { |pred| define_method(:"#{pred}?") { true } }
|
57
82
|
self
|
58
83
|
end
|
59
84
|
|
60
85
|
def is_not(*preds)
|
86
|
+
Pincushion.validate(predicate_pincushion_root, preds)
|
61
87
|
preds.each { |pred| define_method(:"#{pred}?") { false } }
|
62
88
|
self
|
63
89
|
end
|
@@ -76,6 +102,7 @@ module Pincushion
|
|
76
102
|
end
|
77
103
|
|
78
104
|
def that_are(*preds)
|
105
|
+
Pincushion.validate(self, preds)
|
79
106
|
mod = Module.new
|
80
107
|
mod.include self
|
81
108
|
mod.is(*preds)
|
@@ -83,6 +110,7 @@ module Pincushion
|
|
83
110
|
end
|
84
111
|
|
85
112
|
def that_is(*preds)
|
113
|
+
Pincushion.validate(self, preds)
|
86
114
|
klass = Class.new
|
87
115
|
klass.include self
|
88
116
|
klass.is(*preds)
|
data/lib/pincushion/plugins.rb
CHANGED
@@ -1,4 +1,20 @@
|
|
1
1
|
module Pincushion
|
2
|
+
def self.plugins
|
3
|
+
@plugins || []
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.plugin(name)
|
7
|
+
require "pincushion/plugins/#{name}"
|
8
|
+
mod = Plugins.const_get(Plugins.camelize(name))
|
9
|
+
extend mod::PincushionMethods if defined?(mod::PincushionMethods)
|
10
|
+
@plugins ||= []
|
11
|
+
@plugins << name
|
12
|
+
rescue LoadError
|
13
|
+
raise LoadError, "Plugin not found: #{name}"
|
14
|
+
rescue NameError => e
|
15
|
+
raise NameError, "#{e} for plugin: #{name}"
|
16
|
+
end
|
17
|
+
|
2
18
|
module Plugins
|
3
19
|
def self.camelize(string)
|
4
20
|
string.to_s
|
@@ -6,12 +22,16 @@ module Pincushion
|
|
6
22
|
.gsub(/(^|_)(.)/) { Regexp.last_match(2).upcase }
|
7
23
|
end
|
8
24
|
|
25
|
+
attr_reader :plugins
|
26
|
+
|
9
27
|
def plugin(name)
|
10
28
|
require "pincushion/plugins/#{name}"
|
11
29
|
mod = Plugins.const_get(Plugins.camelize(name))
|
12
30
|
extend mod::ModuleMethods if defined?(mod::ModuleMethods)
|
13
31
|
extend mod::RootModuleMethods if defined?(mod::RootModuleMethods)
|
14
32
|
include mod::InstanceMethods if defined?(mod::InstanceMethods)
|
33
|
+
@plugins ||= []
|
34
|
+
@plugins << name
|
15
35
|
rescue LoadError
|
16
36
|
raise LoadError, "Plugin not found: #{name}"
|
17
37
|
rescue NameError => e
|
@@ -1,12 +1,29 @@
|
|
1
1
|
require 'csv'
|
2
2
|
|
3
3
|
module Pincushion
|
4
|
+
def self.from_csv(csv, *args)
|
5
|
+
args << {} unless args.last.is_a?(Hash)
|
6
|
+
args.last.merge!(Plugins::CsvSerializer::OPTS)
|
7
|
+
from_rows(CSV.parse(csv, *args).map(&:to_h))
|
8
|
+
end
|
9
|
+
|
4
10
|
module Plugins
|
5
11
|
module CsvSerializer
|
12
|
+
OPTS = {
|
13
|
+
headers: true,
|
14
|
+
header_converters: :symbol,
|
15
|
+
converters: lambda { |string|
|
16
|
+
case string
|
17
|
+
when "true" then true
|
18
|
+
when "false" then false
|
19
|
+
else string
|
20
|
+
end
|
21
|
+
}
|
22
|
+
}.freeze
|
23
|
+
|
6
24
|
module RootModuleMethods
|
7
25
|
def to_csv(*args, **kwargs)
|
8
|
-
|
9
|
-
kwargs[:headers] ||= [:identifier, :predicate, :value]
|
26
|
+
kwargs[:headers] ||= [:identifier, *predicates]
|
10
27
|
|
11
28
|
CSV.generate(*args, **kwargs) do |csv|
|
12
29
|
rows.each { |row| csv << row }
|
@@ -1,11 +1,19 @@
|
|
1
|
-
require 'multi_json'
|
2
|
-
|
3
1
|
module Pincushion
|
4
2
|
module Plugins
|
5
3
|
module JsonSerializer
|
4
|
+
OPTS = { symbolize_names: true }
|
5
|
+
|
6
|
+
module PincushionMethods
|
7
|
+
def from_json(json, *args)
|
8
|
+
args << {} unless args.last.is_a?(Hash)
|
9
|
+
args.last.merge!(OPTS)
|
10
|
+
from_rows(JSON.parse(json, *args))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
6
14
|
module RootModuleMethods
|
7
15
|
def to_json(*args)
|
8
|
-
|
16
|
+
JSON.dump(rows, *args)
|
9
17
|
end
|
10
18
|
end # module RootModuleMethods
|
11
19
|
end # module JsonSerializer
|
data/lib/pincushion/version.rb
CHANGED
@@ -0,0 +1,95 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "json"
|
3
|
+
require "pincushion"
|
4
|
+
require "pincushion/version"
|
5
|
+
|
6
|
+
describe Pincushion do
|
7
|
+
let(:klass) { Pincushion }
|
8
|
+
|
9
|
+
let(:animal_data) do
|
10
|
+
[
|
11
|
+
{ identifier: "Mee-mow", carnivore: true, herbivore: false },
|
12
|
+
{ identifier: "Jake", carnivore: true, herbivore: true },
|
13
|
+
{ identifier: "B-Mo", carnivore: false, herbivore: false }
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:animal_data_csv) do
|
18
|
+
"identifier,carnivore,herbivore\n"\
|
19
|
+
"Mee-mow,true,false\n"\
|
20
|
+
"Jake,true,true\n"\
|
21
|
+
"B-Mo,false,false\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:animal_data_json) do
|
25
|
+
"[{\"identifier\":\"Mee-mow\",\"carnivore\":true,\"herbivore\":false},"\
|
26
|
+
"{\"identifier\":\"Jake\",\"carnivore\":true,\"herbivore\":true},"\
|
27
|
+
"{\"identifier\":\"B-Mo\",\"carnivore\":false,\"herbivore\":false}]"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "has a version number" do
|
31
|
+
refute_nil ::Pincushion::VERSION
|
32
|
+
end
|
33
|
+
|
34
|
+
it "can be used to define a category with properties" do
|
35
|
+
animals = Module.new
|
36
|
+
animals.include Pincushion
|
37
|
+
animals.predicates :carnivore, :herbivore
|
38
|
+
cat = animals.that_is(:carnivore).named("Mee-mow")
|
39
|
+
mittens = animals.find("Mee-mow")
|
40
|
+
assert_equal mittens.class, cat
|
41
|
+
assert mittens.carnivore?
|
42
|
+
refute mittens.herbivore?
|
43
|
+
end
|
44
|
+
|
45
|
+
it "doesn't allow unregistered predicates" do
|
46
|
+
animals = Module.new
|
47
|
+
animals.include Pincushion
|
48
|
+
animals.predicates :herbivore
|
49
|
+
|
50
|
+
assert_raises Pincushion::MissingPredicateError do
|
51
|
+
animals.that_is(:carnivore)
|
52
|
+
end
|
53
|
+
|
54
|
+
assert_raises Pincushion::MissingPredicateError do
|
55
|
+
cat = animals.that_is
|
56
|
+
cat.is(:carnivore)
|
57
|
+
end
|
58
|
+
|
59
|
+
assert_raises Pincushion::MissingPredicateError do
|
60
|
+
cat = animals.that_is
|
61
|
+
cat.is_not(:carnivore)
|
62
|
+
end
|
63
|
+
|
64
|
+
assert_raises Pincushion::MissingPredicateError do
|
65
|
+
animals.that_are(:carnivore)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "doesn't allow unregistered predicates (empty set)" do
|
70
|
+
animals = Module.new
|
71
|
+
animals.include Pincushion
|
72
|
+
assert_raises Pincushion::MissingPredicateError do
|
73
|
+
animals.that_is(:carnivore)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it "round-trips to and from arrays of hashes" do
|
78
|
+
animals = Pincushion.from_rows(animal_data)
|
79
|
+
assert_equal animals.rows, animal_data
|
80
|
+
end
|
81
|
+
|
82
|
+
it "round-trips CSV with the csv_serializer plugin" do
|
83
|
+
Pincushion.plugin :csv_serializer
|
84
|
+
animals = Pincushion.from_csv(animal_data_csv)
|
85
|
+
animals.plugin :csv_serializer
|
86
|
+
assert_equal animals.to_csv(write_headers: true), animal_data_csv
|
87
|
+
end
|
88
|
+
|
89
|
+
it "round-trips JSON with the json_serializer plugin" do
|
90
|
+
Pincushion.plugin :json_serializer
|
91
|
+
animals = Pincushion.from_json(animal_data_json)
|
92
|
+
animals.plugin :json_serializer
|
93
|
+
assert_equal animals.to_json, animal_data_json
|
94
|
+
end
|
95
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,29 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pincushion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Miller
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
27
55
|
description:
|
28
56
|
email: bmiller@rackspace.com
|
29
57
|
executables: []
|
@@ -35,6 +63,8 @@ files:
|
|
35
63
|
- lib/pincushion/plugins/csv_serializer.rb
|
36
64
|
- lib/pincushion/plugins/json_serializer.rb
|
37
65
|
- lib/pincushion/version.rb
|
66
|
+
- spec/pincushion_spec.rb
|
67
|
+
- spec/spec_helper.rb
|
38
68
|
homepage: https://github.com/bjmllr/pincushion
|
39
69
|
licenses:
|
40
70
|
- MIT
|
@@ -55,8 +85,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
85
|
version: '0'
|
56
86
|
requirements: []
|
57
87
|
rubyforge_project:
|
58
|
-
rubygems_version: 2.
|
88
|
+
rubygems_version: 2.5.1
|
59
89
|
signing_key:
|
60
90
|
specification_version: 4
|
61
91
|
summary: Predicate-centric classification toolkit
|
62
|
-
test_files:
|
92
|
+
test_files:
|
93
|
+
- spec/pincushion_spec.rb
|
94
|
+
- spec/spec_helper.rb
|
95
|
+
has_rdoc:
|