ccp 0.1.7 → 0.2.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.
- data/ccp.gemspec +1 -1
- data/lib/ccp.rb +4 -2
- data/lib/ccp/invokers/base.rb +2 -2
- data/lib/ccp/persistent.rb +23 -0
- data/lib/ccp/persistent/base.rb +51 -0
- data/lib/ccp/persistent/dir.rb +48 -0
- data/lib/ccp/persistent/file.rb +59 -0
- data/lib/ccp/persistent/tsv.rb +76 -0
- data/lib/ccp/persistent/versioned.rb +90 -0
- data/lib/ccp/receivers.rb +4 -1
- data/lib/ccp/receivers/base.rb +6 -7
- data/lib/ccp/receivers/commentable.rb +1 -1
- data/lib/ccp/receivers/core.rb +14 -0
- data/lib/ccp/receivers/fixtures.rb +75 -0
- data/lib/ccp/receivers/profileable.rb +1 -1
- data/lib/ccp/receivers/settings.rb +21 -0
- data/lib/ccp/receivers/variables.rb +21 -0
- data/lib/ccp/serializers.rb +19 -0
- data/lib/ccp/serializers/core.rb +13 -0
- data/lib/ccp/serializers/json.rb +15 -0
- data/lib/ccp/serializers/yaml.rb +15 -0
- data/lib/ccp/utils.rb +6 -0
- data/lib/ccp/utils/colorize.rb +15 -0
- data/lib/ccp/version.rb +1 -1
- data/spec/{commands_base_spec.rb → commands/base_spec.rb} +0 -0
- data/spec/{commands_composite_spec.rb → commands/composite_spec.rb} +0 -0
- data/spec/{commands_core_spec.rb → commands/core_spec.rb} +0 -0
- data/spec/{commands_executable_spec.rb → commands/executable_spec.rb} +0 -0
- data/spec/{invokers_spec.rb → invokers/base_spec.rb} +0 -0
- data/spec/persistent/base_spec.rb +49 -0
- data/spec/persistent/dir_spec.rb +111 -0
- data/spec/persistent/file_spec.rb +124 -0
- data/spec/persistent/tsv_spec.rb +19 -0
- data/spec/persistent/versioned_spec.rb +110 -0
- data/spec/receivers/fixture_save_spec.rb +79 -0
- data/spec/serializers/core_spec.rb +19 -0
- data/spec/serializers/json_spec.rb +27 -0
- data/spec/serializers/spec.rb +39 -0
- data/spec/serializers/yaml_spec.rb +27 -0
- metadata +39 -18
- data/lib/ccp/colorize.rb +0 -13
- data/lib/ccp/data.rb +0 -37
- data/lib/ccp/receivers/save_fixture.rb +0 -45
- data/spec/data_spec.rb +0 -18
- data/spec/save_fixture_spec.rb +0 -47
@@ -0,0 +1,75 @@
|
|
1
|
+
module Ccp
|
2
|
+
module Receivers
|
3
|
+
module Fixtures
|
4
|
+
class Storage
|
5
|
+
def initialize(kvs)
|
6
|
+
@kvs = kvs
|
7
|
+
end
|
8
|
+
|
9
|
+
def save(data)
|
10
|
+
data.keys.each do |key|
|
11
|
+
@kvs[key.to_s] = data[key]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def load
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute(cmd)
|
21
|
+
return super unless fixtures_save?(cmd)
|
22
|
+
|
23
|
+
observer = Ccp::Fixtures::Observer.new(data)
|
24
|
+
observer.start
|
25
|
+
super
|
26
|
+
observer.stop
|
27
|
+
|
28
|
+
fixtures_save(cmd, observer.read, observer.write)
|
29
|
+
end
|
30
|
+
|
31
|
+
def setup
|
32
|
+
super
|
33
|
+
|
34
|
+
self[:fixture_save] = Object # Schema
|
35
|
+
|
36
|
+
self[:fixture_dir] = "tmp/fixtures"
|
37
|
+
self[:fixture_kvs] = :file
|
38
|
+
self[:fixture_ext] = :json
|
39
|
+
self[:fixture_save] = proc{|cmd| false }
|
40
|
+
self[:fixture_path_for] = proc{|cmd| settings.path(:fixture_dir) + cmd.class.name.underscore}
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse!(options)
|
44
|
+
settings.keys.grep(/^fixture_/).each do |key|
|
45
|
+
self[key] = options.delete(key.to_sym) if options.has_key?(key.to_sym)
|
46
|
+
self[key] = options.delete(key) if options.has_key?(key)
|
47
|
+
end
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
def fixtures_save?(cmd)
|
52
|
+
case (obj = self[:fixture_save])
|
53
|
+
when true ; obj
|
54
|
+
when false; obj
|
55
|
+
when Proc; obj.call(cmd)
|
56
|
+
else; raise ":fixture_save is invalid: #{obj.class}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def fixtures_save(cmd, read, write)
|
61
|
+
path = self[:fixture_path_for].call(cmd)
|
62
|
+
versioned = Ccp::Persistent::Versioned.new(path, :kvs=>self[:fixture_kvs], :ext=>self[:fixture_ext])
|
63
|
+
versioned["read" ].save(read)
|
64
|
+
versioned["write"].save(write)
|
65
|
+
end
|
66
|
+
|
67
|
+
def fixtures_for(cmd, key)
|
68
|
+
kvs = Ccp::Persistent.lookup(self[:fixture_kvs])
|
69
|
+
code = Ccp::Serializers.lookup(self[:fixture_ext])
|
70
|
+
path = self[:fixture_path_for].call(cmd) + "#{key}.#{code.ext}.#{kvs.ext}"
|
71
|
+
return Storage.new(kvs.new(path, code))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
# provide variables used in receiver itself
|
4
|
+
|
5
|
+
module Ccp
|
6
|
+
module Receivers
|
7
|
+
module Settings
|
8
|
+
def settings
|
9
|
+
@settings ||= Typed::Hash.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](key)
|
13
|
+
settings[key]
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(key, val)
|
17
|
+
settings[key] = val
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
# provide variables shared by commands
|
4
|
+
|
5
|
+
module Ccp
|
6
|
+
module Receivers
|
7
|
+
module Variables
|
8
|
+
def data
|
9
|
+
@data ||= Typed::Hash.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def data?(key)
|
13
|
+
data.set?(key)
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse!(options)
|
17
|
+
data.merge!(options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Ccp::Serializers
|
2
|
+
NotFound = Class.new(RuntimeError)
|
3
|
+
|
4
|
+
autoload :Core , 'ccp/serializers/core'
|
5
|
+
autoload :Json , 'ccp/serializers/json'
|
6
|
+
autoload :Yaml , 'ccp/serializers/yaml'
|
7
|
+
|
8
|
+
def self.lookup(name)
|
9
|
+
case name
|
10
|
+
when :json, 'json'; Ccp::Serializers::Json
|
11
|
+
when :yaml, 'yaml'; Ccp::Serializers::Yaml
|
12
|
+
else
|
13
|
+
Ccp::Serializers::Core.instance_methods.each do |key|
|
14
|
+
name.must.duck(key) { raise NotFound, "%s: %s" % [name.class, name] }
|
15
|
+
end
|
16
|
+
return name
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Ccp::Serializers::Core
|
2
|
+
def ext
|
3
|
+
raise NotImplementedError, "subclass resposibility"
|
4
|
+
end
|
5
|
+
|
6
|
+
def encode(val)
|
7
|
+
raise NotImplementedError, "subclass resposibility"
|
8
|
+
end
|
9
|
+
|
10
|
+
def decode(val)
|
11
|
+
raise NotImplementedError, "subclass resposibility"
|
12
|
+
end
|
13
|
+
end
|
data/lib/ccp/utils.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Ccp
|
2
|
+
module Utils
|
3
|
+
module Colorize
|
4
|
+
def colorize(text, ansi); "#{ansi}#{text}\e[0m"; end
|
5
|
+
def red (text); colorize(text, "\e[31m"); end
|
6
|
+
def green (text); colorize(text, "\e[32m"); end
|
7
|
+
def yellow(text); colorize(text, "\e[33m"); end
|
8
|
+
def blue (text); colorize(text, "\e[34m"); end
|
9
|
+
def pink (text); colorize(text, "\e[35m"); end
|
10
|
+
def aqua (text); colorize(text, "\e[36m"); end
|
11
|
+
|
12
|
+
extend self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/ccp/version.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
describe Ccp::Persistent::Base do
|
6
|
+
subject { Ccp::Persistent::Base.new(:source, Ccp::Serializers::Json) }
|
7
|
+
|
8
|
+
describe "#source" do
|
9
|
+
it "should return source" do
|
10
|
+
subject.source.should == :source
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should provide ext" do
|
15
|
+
subject.methods.include?("ext").should == true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should provide exist?" do
|
19
|
+
subject.methods.include?("exist?").should == true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should provide #save" do
|
23
|
+
subject.methods.include?("save").should == true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should provide #load!" do
|
27
|
+
subject.methods.include?("load!").should == true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should provide #load" do
|
31
|
+
subject.methods.include?("load").should == true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should provide #[]" do
|
35
|
+
subject.methods.include?("[]").should == true
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should provide #[]=" do
|
39
|
+
subject.methods.include?("[]=").should == true
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should provide #keys" do
|
43
|
+
subject.methods.include?("keys").should == true
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should provide #truncate" do
|
47
|
+
subject.methods.include?("truncate").should == true
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
describe Ccp::Persistent::Dir do
|
6
|
+
def root; Pathname("tmp/spec/ccp/persistent/dir"); end
|
7
|
+
def db1 ; root + "db1"; end
|
8
|
+
def db2 ; root + "db2"; end
|
9
|
+
|
10
|
+
before do
|
11
|
+
FileUtils.rm_rf(root)
|
12
|
+
root.mkpath
|
13
|
+
end
|
14
|
+
|
15
|
+
describe ".ext" do
|
16
|
+
it "should return ''" do
|
17
|
+
Ccp::Persistent::Dir.ext.should == ''
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#path" do
|
22
|
+
it "should return the given source" do
|
23
|
+
kvs = Ccp::Persistent::Dir.new(root, :json)
|
24
|
+
kvs.path.to_s.should == root.to_s
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#[]=" do
|
29
|
+
it "should create data.file into <dir>/<key>.<ext>" do
|
30
|
+
kvs = Ccp::Persistent::Dir.new(root, :json)
|
31
|
+
kvs[:foo] = "[1,2,3]"
|
32
|
+
(root + "foo.json").should exist
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#load!" do
|
37
|
+
it "should fetch data if exists" do
|
38
|
+
(root + "foo.json").open("w+"){|f| f.print "1"}
|
39
|
+
kvs = Ccp::Persistent::Dir.new(root, :json)
|
40
|
+
kvs.load!(:foo).should == 1
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should raise NotFound if not exists" do
|
44
|
+
kvs = Ccp::Persistent::Dir.new(root, :json)
|
45
|
+
lambda {
|
46
|
+
kvs.load!(:foo)
|
47
|
+
}.should raise_error(Ccp::Persistent::NotFound)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#load" do
|
52
|
+
it "should fetch data if exists" do
|
53
|
+
(root + "foo.json").open("w+"){|f| f.print "1"}
|
54
|
+
kvs = Ccp::Persistent::Dir.new(root, :json)
|
55
|
+
kvs.load(:foo).should == 1
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return nil if not exists" do
|
59
|
+
kvs = Ccp::Persistent::Dir.new(root, :json)
|
60
|
+
kvs.load(:foo).should == nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#[]" do
|
65
|
+
it "should fetch data if exists" do
|
66
|
+
(root + "foo.json").open("w+"){|f| f.print "1"}
|
67
|
+
kvs = Ccp::Persistent::Dir.new(root, :json)
|
68
|
+
kvs.load!(:foo).should == 1
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should raise NotFound if not exists" do
|
72
|
+
kvs = Ccp::Persistent::Dir.new(root, :json)
|
73
|
+
lambda {
|
74
|
+
kvs.load!(:foo)
|
75
|
+
}.should raise_error(Ccp::Persistent::NotFound)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#keys" do
|
80
|
+
it "should return a sorted array of key names filtered by given ext" do
|
81
|
+
["1.json", "2.yaml", "3.json"].each do |i|
|
82
|
+
(root + i).open("w+"){}
|
83
|
+
end
|
84
|
+
|
85
|
+
kvs = Ccp::Persistent::Dir.new(root, :json)
|
86
|
+
kvs.keys.should == ["1","3"]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#truncate" do
|
91
|
+
it "should delete all *.<ext>" do
|
92
|
+
["1.json", "2.yaml", "3.json"].each do |i|
|
93
|
+
(root + i).open("w+"){}
|
94
|
+
end
|
95
|
+
root.children.map{|i| i.basename.to_s}.sort.should == ["1.json", "2.yaml", "3.json"]
|
96
|
+
|
97
|
+
kvs = Ccp::Persistent::Dir.new(root, :json)
|
98
|
+
kvs.truncate
|
99
|
+
root.children.map{|i| i.basename.to_s}.sort.should == ["2.yaml"]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should save data into storage and load it" do
|
104
|
+
kvs = Ccp::Persistent::Dir.new(db1, :json)
|
105
|
+
kvs[:foo] = "[1,2,3]"
|
106
|
+
|
107
|
+
FileUtils.mv(db1, db2)
|
108
|
+
kvs = Ccp::Persistent::Dir.new(db2, :json)
|
109
|
+
kvs[:foo].should == "[1,2,3]"
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
describe Ccp::Persistent::File do
|
6
|
+
def db; Pathname("tmp/spec/ccp/persistent/json/db.json"); end
|
7
|
+
|
8
|
+
before do
|
9
|
+
FileUtils.rm_rf(db)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".ext" do
|
13
|
+
it "should return ''" do
|
14
|
+
Ccp::Persistent::File.ext.should == ''
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#path" do
|
19
|
+
it "should return the given source if its ext is json" do
|
20
|
+
kvs = Ccp::Persistent::File.new("tmp/foo.json", :json)
|
21
|
+
kvs.path.to_s.should == "tmp/foo.json"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return <given source>.json if its ext is not json" do
|
25
|
+
kvs = Ccp::Persistent::File.new("tmp/foo", :json)
|
26
|
+
kvs.path.to_s.should == "tmp/foo.json"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#[]=" do
|
31
|
+
it "should create a json file" do
|
32
|
+
db.should_not exist
|
33
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
34
|
+
kvs["foo"] = "[1,2,3]"
|
35
|
+
db.should exist
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should write json data as hash" do
|
39
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
40
|
+
kvs["foo"] = "[1,2,3]"
|
41
|
+
db.read{}.should == '{"foo":"[1,2,3]"}'
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should convert key to string" do
|
45
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
46
|
+
kvs[:foo] = "[1,2,3]"
|
47
|
+
db.read{}.should == '{"foo":"[1,2,3]"}'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#load!" do
|
52
|
+
it "should raise NotFound if not exists" do
|
53
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
54
|
+
lambda {
|
55
|
+
kvs.load!("foo")
|
56
|
+
}.should raise_error(Ccp::Persistent::NotFound)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should fetch data if exists" do
|
60
|
+
db.open("w+"){|f| f.print(JSON.dump({"foo" => 1}))}
|
61
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
62
|
+
kvs.load!("foo").should == 1
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should convert key to string" do
|
66
|
+
db.open("w+"){|f| f.print(JSON.dump({"foo" => 1}))}
|
67
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
68
|
+
kvs.load!(:foo).should == 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#load" do
|
73
|
+
it "should return nil if not exists" do
|
74
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
75
|
+
kvs.load("foo2").should == nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should fetch data if exists" do
|
79
|
+
db.open("w+"){|f| f.print(JSON.dump({"foo" => 1}))}
|
80
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
81
|
+
kvs.load("foo").should == 1
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should convert key to string" do
|
85
|
+
db.open("w+"){|f| f.print(JSON.dump({"foo" => 1}))}
|
86
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
87
|
+
kvs.load(:foo).should == 1
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#[]" do
|
92
|
+
it "should fetch data if exists" do
|
93
|
+
db.open("w+"){|f| f.print(JSON.dump({"foo" => 1}))}
|
94
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
95
|
+
kvs.load!(:foo).should == 1
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should raise NotFound if not exists" do
|
99
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
100
|
+
lambda {
|
101
|
+
kvs.load!(:foo)
|
102
|
+
}.should raise_error(Ccp::Persistent::NotFound)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "#keys" do
|
107
|
+
it "should return a sorted array of key names filtered by given ext" do
|
108
|
+
db.open("w+"){|f| f.print(JSON.dump({"foo" => 1, "bar" => "xxx"}))}
|
109
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
110
|
+
kvs.keys.should == ["bar", "foo"]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "#truncate" do
|
115
|
+
it "should delete its db file" do
|
116
|
+
db.open("w+"){|f| f.print(JSON.dump({"foo" => 1}))}
|
117
|
+
db.should exist
|
118
|
+
|
119
|
+
kvs = Ccp::Persistent::File.new(db, :json)
|
120
|
+
kvs.truncate
|
121
|
+
db.should_not exist
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|