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.
Files changed (45) hide show
  1. data/ccp.gemspec +1 -1
  2. data/lib/ccp.rb +4 -2
  3. data/lib/ccp/invokers/base.rb +2 -2
  4. data/lib/ccp/persistent.rb +23 -0
  5. data/lib/ccp/persistent/base.rb +51 -0
  6. data/lib/ccp/persistent/dir.rb +48 -0
  7. data/lib/ccp/persistent/file.rb +59 -0
  8. data/lib/ccp/persistent/tsv.rb +76 -0
  9. data/lib/ccp/persistent/versioned.rb +90 -0
  10. data/lib/ccp/receivers.rb +4 -1
  11. data/lib/ccp/receivers/base.rb +6 -7
  12. data/lib/ccp/receivers/commentable.rb +1 -1
  13. data/lib/ccp/receivers/core.rb +14 -0
  14. data/lib/ccp/receivers/fixtures.rb +75 -0
  15. data/lib/ccp/receivers/profileable.rb +1 -1
  16. data/lib/ccp/receivers/settings.rb +21 -0
  17. data/lib/ccp/receivers/variables.rb +21 -0
  18. data/lib/ccp/serializers.rb +19 -0
  19. data/lib/ccp/serializers/core.rb +13 -0
  20. data/lib/ccp/serializers/json.rb +15 -0
  21. data/lib/ccp/serializers/yaml.rb +15 -0
  22. data/lib/ccp/utils.rb +6 -0
  23. data/lib/ccp/utils/colorize.rb +15 -0
  24. data/lib/ccp/version.rb +1 -1
  25. data/spec/{commands_base_spec.rb → commands/base_spec.rb} +0 -0
  26. data/spec/{commands_composite_spec.rb → commands/composite_spec.rb} +0 -0
  27. data/spec/{commands_core_spec.rb → commands/core_spec.rb} +0 -0
  28. data/spec/{commands_executable_spec.rb → commands/executable_spec.rb} +0 -0
  29. data/spec/{invokers_spec.rb → invokers/base_spec.rb} +0 -0
  30. data/spec/persistent/base_spec.rb +49 -0
  31. data/spec/persistent/dir_spec.rb +111 -0
  32. data/spec/persistent/file_spec.rb +124 -0
  33. data/spec/persistent/tsv_spec.rb +19 -0
  34. data/spec/persistent/versioned_spec.rb +110 -0
  35. data/spec/receivers/fixture_save_spec.rb +79 -0
  36. data/spec/serializers/core_spec.rb +19 -0
  37. data/spec/serializers/json_spec.rb +27 -0
  38. data/spec/serializers/spec.rb +39 -0
  39. data/spec/serializers/yaml_spec.rb +27 -0
  40. metadata +39 -18
  41. data/lib/ccp/colorize.rb +0 -13
  42. data/lib/ccp/data.rb +0 -37
  43. data/lib/ccp/receivers/save_fixture.rb +0 -45
  44. data/spec/data_spec.rb +0 -18
  45. data/spec/save_fixture_spec.rb +0 -47
@@ -0,0 +1,14 @@
1
+ module Ccp
2
+ module Receivers
3
+ module Core
4
+ def setup
5
+ end
6
+
7
+ def inspect
8
+ klass_name = self.class.name.to_s.split(/::/).last
9
+
10
+ "#<Receivers::#{klass_name} data:#{data.inspect}>"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -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
@@ -1,7 +1,7 @@
1
1
  module Ccp
2
2
  module Receivers
3
3
  module Profileable
4
- include Colorize
4
+ include Utils::Colorize
5
5
 
6
6
  Profile = Struct.new(:target, :method, :time)
7
7
  class Profile
@@ -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
@@ -0,0 +1,15 @@
1
+ module Ccp::Serializers::Json
2
+ include Ccp::Serializers::Core
3
+
4
+ def self.ext
5
+ "json"
6
+ end
7
+
8
+ def self.encode(val)
9
+ JSON.dump(val)
10
+ end
11
+
12
+ def self.decode(val)
13
+ JSON.load(val)
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Ccp::Serializers::Yaml
2
+ include Ccp::Serializers::Core
3
+
4
+ def self.ext
5
+ "yaml"
6
+ end
7
+
8
+ def self.encode(val)
9
+ val.to_yaml
10
+ end
11
+
12
+ def self.decode(val)
13
+ YAML.load(val)
14
+ end
15
+ end
data/lib/ccp/utils.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Ccp
2
+ module Utils
3
+ autoload :Data , 'ccp/utils/data'
4
+ autoload :Colorize , 'ccp/utils/colorize'
5
+ end
6
+ end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Ccp
2
- VERSION = "0.1.7"
2
+ VERSION = "0.2.0"
3
3
  end
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