pico 0.0.1
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 +7 -0
- data/.gitignore +24 -0
- data/.vimrc +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +33 -0
- data/gold_master_apps/tic_tac_toe/Gemfile +18 -0
- data/gold_master_apps/tic_tac_toe/Rakefile +3 -0
- data/gold_master_apps/tic_tac_toe/boot.rb +2 -0
- data/gold_master_apps/tic_tac_toe/config/application.rb +8 -0
- data/gold_master_apps/tic_tac_toe/config/environments/test.rb +3 -0
- data/gold_master_apps/tic_tac_toe/game/bad_move.rb +1 -0
- data/gold_master_apps/tic_tac_toe/game/game.rb +62 -0
- data/gold_master_apps/tic_tac_toe/game/make_move_command.rb +38 -0
- data/gold_master_apps/tic_tac_toe/game/memory_repository.rb +39 -0
- data/gold_master_apps/tic_tac_toe/test/game_test.rb +65 -0
- data/gold_master_apps/tic_tac_toe/test/reports/TEST-GameTest.xml +13 -0
- data/gold_master_apps/tic_tac_toe/test/test_helper.rb +7 -0
- data/lib/pico.rb +41 -0
- data/lib/pico/application.rb +120 -0
- data/lib/pico/autoloader.rb +131 -0
- data/lib/pico/context.rb +89 -0
- data/lib/pico/context/const_resolver.rb +80 -0
- data/lib/pico/pry_context.rb +71 -0
- data/lib/pico/rake.rb +15 -0
- data/lib/pico/ruse_extensions.rb +9 -0
- data/lib/pico/string_inflections.rb +30 -0
- data/lib/pico/test_runner.rb +27 -0
- data/lib/pico/version.rb +3 -0
- data/pico.gemspec +30 -0
- data/test/integration/autoloading_test.rb +47 -0
- data/test/support/fakes_filesystem.rb +182 -0
- data/test/support/tests_autoloading.rb +16 -0
- data/test/test_helper.rb +36 -0
- data/test/unit/application_test.rb +79 -0
- data/test/unit/autoloader_test.rb +68 -0
- data/test/unit/context_test.rb +80 -0
- metadata +202 -0
data/lib/pico/rake.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
task :env do
|
2
|
+
Pico.application.root = Rake.application.original_dir
|
3
|
+
end
|
4
|
+
|
5
|
+
desc "Open up a console"
|
6
|
+
task console: :env do
|
7
|
+
require "pico/pry_context"
|
8
|
+
Pico::PryContext.start!
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Run the test suite"
|
12
|
+
task test: :env do
|
13
|
+
require "pico/test_runner"
|
14
|
+
Pico::TestRunner.run!
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Pico
|
2
|
+
module StringInflections
|
3
|
+
refine String do
|
4
|
+
def to_camel_case
|
5
|
+
str = "_#{self}"
|
6
|
+
str.gsub!(%r{_[a-z]}) { |snake| snake.slice(1).upcase }
|
7
|
+
str.gsub!('/', '::')
|
8
|
+
str
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_snake_case
|
12
|
+
str = gsub '::', '/'
|
13
|
+
# Convert FOOBar => FooBar
|
14
|
+
str.gsub! %r{[[:upper:]]{2,}} do |uppercase|
|
15
|
+
bit = uppercase[0]
|
16
|
+
bit << uppercase[1...-1].downcase
|
17
|
+
bit << uppercase[-1]
|
18
|
+
bit
|
19
|
+
end
|
20
|
+
str.gsub! %r{[[:lower:]][[:upper:]]+[[:lower:]]} do |camel|
|
21
|
+
bit = camel[0]
|
22
|
+
bit << '_'
|
23
|
+
bit << camel[1..-1].downcase
|
24
|
+
end
|
25
|
+
str.downcase!
|
26
|
+
str
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Pico
|
2
|
+
module TestRunner
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def run!
|
6
|
+
Bundler.require :test
|
7
|
+
|
8
|
+
pid = fork do
|
9
|
+
Pico.shutdown! # For when we're inside pry
|
10
|
+
%w(test spec).each do |test_dir| load_test_files_in test_dir; end
|
11
|
+
Minitest.autorun
|
12
|
+
end
|
13
|
+
|
14
|
+
_, status = Process.wait2 pid
|
15
|
+
status.exitstatus == 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_test_files_in(test_dir)
|
19
|
+
path = Pico.application.root.join(test_dir)
|
20
|
+
return unless path.directory?
|
21
|
+
$LOAD_PATH << path
|
22
|
+
Dir[path.join("**/*_#{test_dir}.rb")].each do |test_file|
|
23
|
+
load test_file
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/pico/version.rb
ADDED
data/pico.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'pico/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "pico"
|
8
|
+
spec.version = Pico::VERSION
|
9
|
+
spec.authors = ["ntl"]
|
10
|
+
spec.email = ["nathanladd+github@gmail.com"]
|
11
|
+
spec.summary = %q{Pico is a micro framework designed to get you some basic, essential functionality and then get out of your way.}
|
12
|
+
spec.description = %q{A very light weight framework for ruby designed to handle a small number of details common to most every application.}
|
13
|
+
spec.homepage = "https://github.com/ntl/pico"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^test/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "ruse", "~> 0.0.4"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
24
|
+
spec.add_development_dependency "colorize"
|
25
|
+
spec.add_development_dependency "fakefs"
|
26
|
+
spec.add_development_dependency "minitest"
|
27
|
+
spec.add_development_dependency "minitest-reporters"
|
28
|
+
spec.add_development_dependency "pry"
|
29
|
+
spec.add_development_dependency "rake"
|
30
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AutoloadingTest < Minitest::Test
|
4
|
+
include FakesFilesystem
|
5
|
+
include TestsAutoloading
|
6
|
+
|
7
|
+
def test_simple_case
|
8
|
+
assert_equal 'hello from A::AA', Foo::A.references_aa
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_negative_case
|
12
|
+
assert_raises NameError do
|
13
|
+
Foo::A.references_abracadabra
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_deeply_nested_module_with_implicit_namespaces
|
18
|
+
assert_equal 'hello from C::CA::CAA::CAAA', Foo::A.references_caaa
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_reference_from_within_constant
|
22
|
+
assert_equal 'hello from A', Foo::D.references_a
|
23
|
+
assert_equal 'hello from B::BA', Foo::D.new.references_b_ba
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_invoking_method_inside_implicit_namespace_raises_error
|
27
|
+
exception = assert_raises NameError do
|
28
|
+
Foo::C.hello
|
29
|
+
end
|
30
|
+
assert_equal "uninitialized constant C (in Foo)", exception.message
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_raises_name_error_if_no_context_found
|
34
|
+
exception = assert_raises NameError do
|
35
|
+
Abracadabra
|
36
|
+
end
|
37
|
+
assert_equal "uninitialized constant Abracadabra", exception.message
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_application_autoload_paths
|
41
|
+
Pico.application.resolve_const 'A'
|
42
|
+
assert_equal 'hello from MyApp::A', MyApp::A.message
|
43
|
+
# Implicit namespace
|
44
|
+
assert_equal 'hello from MyApp::B::BA', MyApp::A.references_b_ba
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
module FakesFilesystem
|
2
|
+
def before_setup
|
3
|
+
super
|
4
|
+
FakeFS::FileSystem.clear
|
5
|
+
FakeFS.activate!
|
6
|
+
World.build!
|
7
|
+
monkeypatch_assert!
|
8
|
+
end
|
9
|
+
|
10
|
+
def after_teardown
|
11
|
+
unmonkeypatch_assert!
|
12
|
+
FakeFS.deactivate!
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def monkeypatch_assert!
|
19
|
+
Minitest::Assertions.module_eval do
|
20
|
+
alias_method :orig_diff, :diff
|
21
|
+
def diff(*args)
|
22
|
+
FakeFS.without { orig_diff *args }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def unmonkeypatch_assert!
|
28
|
+
Minitest::Assertions.module_eval do
|
29
|
+
undef_method :diff
|
30
|
+
alias_method :diff, :orig_diff
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module World
|
35
|
+
extend self
|
36
|
+
|
37
|
+
def build!
|
38
|
+
Dir.mkdir '/foo'
|
39
|
+
|
40
|
+
File.write "/foo/a.rb", <<-FILE
|
41
|
+
module A
|
42
|
+
def self.message
|
43
|
+
"hello from A"
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.references_aa
|
47
|
+
AA.message
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.references_abracadabra
|
51
|
+
Abracadabra.message
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.references_caaa
|
55
|
+
C::CA::CAA::CAAA.message
|
56
|
+
end
|
57
|
+
|
58
|
+
module AB
|
59
|
+
def self.message
|
60
|
+
"hello from A::AB"
|
61
|
+
end
|
62
|
+
|
63
|
+
module ABA
|
64
|
+
def self.message
|
65
|
+
"hello from A::AB::ABA"
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.references_abb
|
69
|
+
ABB.message
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
FILE
|
75
|
+
|
76
|
+
Dir.mkdir "/foo/a"
|
77
|
+
File.write "/foo/a/aa.rb", <<-FILE
|
78
|
+
module A
|
79
|
+
module AA
|
80
|
+
def self.message
|
81
|
+
"hello from A::AA"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
FILE
|
86
|
+
|
87
|
+
Dir.mkdir "/foo/a/ab"
|
88
|
+
File.write "/foo/a/ab/abb.rb", <<-FILE
|
89
|
+
module A
|
90
|
+
module AB
|
91
|
+
module ABB
|
92
|
+
def self.message
|
93
|
+
"hello from A::AB::ABB"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
FILE
|
99
|
+
|
100
|
+
Dir.mkdir "/foo/b"
|
101
|
+
File.write "/foo/b/ba.rb", <<-FILE
|
102
|
+
module B
|
103
|
+
module BA
|
104
|
+
def self.message
|
105
|
+
"hello from B::BA"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
FILE
|
110
|
+
|
111
|
+
Dir.mkdir "/foo/c"
|
112
|
+
Dir.mkdir "/foo/c/ca"
|
113
|
+
Dir.mkdir "/foo/c/ca/caa"
|
114
|
+
File.write "/foo/c/ca/caa/caaa.rb", <<-FILE
|
115
|
+
module C
|
116
|
+
module CA
|
117
|
+
module CAA
|
118
|
+
module CAAA
|
119
|
+
def self.message
|
120
|
+
"hello from C::CA::CAA::CAAA"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
FILE
|
127
|
+
|
128
|
+
File.write "/foo/d.rb", <<-FILE
|
129
|
+
class D
|
130
|
+
def self.references_a
|
131
|
+
A.message
|
132
|
+
end
|
133
|
+
def references_b_ba
|
134
|
+
B::BA.message
|
135
|
+
end
|
136
|
+
end
|
137
|
+
FILE
|
138
|
+
|
139
|
+
Dir.mkdir "/bar"
|
140
|
+
File.write "/bar/a.rb", <<-FILE
|
141
|
+
module A
|
142
|
+
def self.message
|
143
|
+
"hello from Bar::A"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
FILE
|
147
|
+
|
148
|
+
File.write "/bar/b.rb", <<-FILE
|
149
|
+
module B
|
150
|
+
def self.message
|
151
|
+
"hello from Bar::B"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
FILE
|
155
|
+
|
156
|
+
Dir.mkdir "/my_app"
|
157
|
+
Dir.mkdir "/my_app/lib"
|
158
|
+
File.write "/my_app/lib/a.rb", <<-FILE
|
159
|
+
module A
|
160
|
+
def self.message
|
161
|
+
"hello from MyApp::A"
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.references_b_ba
|
165
|
+
B::BA.message
|
166
|
+
end
|
167
|
+
end
|
168
|
+
FILE
|
169
|
+
|
170
|
+
Dir.mkdir "/my_app/lib/b"
|
171
|
+
File.write "/my_app/lib/b/ba.rb", <<-FILE
|
172
|
+
module B
|
173
|
+
module BA
|
174
|
+
def self.message
|
175
|
+
"hello from MyApp::B::BA"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
FILE
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module TestsAutoloading
|
2
|
+
def setup
|
3
|
+
@foo = Pico.define_context :Foo, root: "/foo"
|
4
|
+
@bar = Pico.define_context :Bar, root: '/bar', parent: :Foo
|
5
|
+
@app = Pico.define_application :MyApp, root: "/my_app" do
|
6
|
+
self.autoload_paths << 'lib'
|
7
|
+
end
|
8
|
+
Pico.boot!
|
9
|
+
assert_nil Pico::Autoloader.current_autoloader
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
assert_nil Pico::Autoloader.current_autoloader,
|
14
|
+
"Each test in this file must clean up after itself"
|
15
|
+
end
|
16
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
require "minitest/autorun"
|
5
|
+
require "minitest/reporters"
|
6
|
+
|
7
|
+
require "colorize"
|
8
|
+
require "fakefs/safe"
|
9
|
+
require "ostruct"
|
10
|
+
require "pathname"
|
11
|
+
require "stringio"
|
12
|
+
|
13
|
+
Minitest::Reporters.use! Minitest::Reporters::DefaultReporter.new
|
14
|
+
|
15
|
+
require_relative "../lib/pico"
|
16
|
+
|
17
|
+
$LOAD_PATH << "test/support"
|
18
|
+
|
19
|
+
Minitest::Test.class_eval do
|
20
|
+
autoload :FakesFilesystem, "fakes_filesystem"
|
21
|
+
autoload :TestsAutoloading, "tests_autoloading"
|
22
|
+
|
23
|
+
def after_teardown
|
24
|
+
Pico.shutdown!
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Binding
|
29
|
+
def method_missing(sym, *)
|
30
|
+
return super unless sym == :pry
|
31
|
+
FakeFS.without do
|
32
|
+
require 'pry'
|
33
|
+
pry
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ApplicationTest < Minitest::Test
|
4
|
+
def test_defining_an_application
|
5
|
+
Pico.define_application :Foo
|
6
|
+
Pico.boot!
|
7
|
+
refute_nil Pico.application
|
8
|
+
assert_equal :Foo, Pico.application.name
|
9
|
+
assert_equal Pathname(__FILE__).dirname, Pico.application.root
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_autoload_paths
|
13
|
+
Pico.define_application :Foo do
|
14
|
+
self.autoload_paths = %w(lib app)
|
15
|
+
end
|
16
|
+
|
17
|
+
assert_equal %w(lib app), Pico.application.autoload_paths
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_providing_objects
|
21
|
+
Pico.define_application :Foo do
|
22
|
+
provide as: 'foo' do :provided_foo; end
|
23
|
+
provide :provided_bar, as: 'bar'
|
24
|
+
provide 'MyClass', as: 'baz'
|
25
|
+
end
|
26
|
+
Pico.boot!
|
27
|
+
|
28
|
+
my_class = Class.new do def message; :provided_baz; end ; end
|
29
|
+
Object.const_set :MyClass, my_class
|
30
|
+
|
31
|
+
consumer = Class.new do
|
32
|
+
attr :foo, :bar, :baz, :ping
|
33
|
+
def initialize(foo, bar, baz, ping:)
|
34
|
+
@foo = foo ; @bar = bar ; @baz = baz; @ping = ping
|
35
|
+
end
|
36
|
+
end
|
37
|
+
Foo.const_set :Consumer, consumer
|
38
|
+
|
39
|
+
obj = Foo.build(:Consumer, ping: 'pong')
|
40
|
+
assert_equal :provided_foo, obj.foo
|
41
|
+
assert_equal :provided_bar, obj.bar
|
42
|
+
assert_equal :provided_baz, obj.baz.message
|
43
|
+
assert_equal 'pong', obj.ping
|
44
|
+
|
45
|
+
ensure
|
46
|
+
Object.send :remove_const, :MyClass
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_wraps_ruse_errors
|
50
|
+
Pico.define_application :Foo
|
51
|
+
Pico.boot!
|
52
|
+
|
53
|
+
consumer = Class.new do
|
54
|
+
attr :unmet_dep
|
55
|
+
def initialize(unmet_dep)
|
56
|
+
@unmet_dep = unmet_dep
|
57
|
+
end
|
58
|
+
end
|
59
|
+
Foo.const_set :Consumer, consumer
|
60
|
+
|
61
|
+
exception = assert_raises Pico::Exception do
|
62
|
+
Foo.build(:Consumer)
|
63
|
+
end
|
64
|
+
|
65
|
+
assert_equal "could not resolve dependency `unmet_dep'", exception.message
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_cannot_provide_object_as_block_and_arg
|
69
|
+
exception = assert_raises ArgumentError do
|
70
|
+
Pico.define_application :Foo do
|
71
|
+
provide :a_value, as: :foo do
|
72
|
+
:another_value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
assert_equal "cannot supply a block and a value", exception.message
|
78
|
+
end
|
79
|
+
end
|