lawyer 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e99be433808f11cb424f36b57b3ac474f2cd810e
4
+ data.tar.gz: 9eeebb6c71f45d45e054aa3a66a310409de86587
5
+ SHA512:
6
+ metadata.gz: 6c2f4dd3603a8dd235adfd3efb6c7ad08a075f2410cb7b835e7c9b78a876e0194ed00c9bb2c6c9359b64d3fbc1764d982bc1e962c081a852d08452b93630f4df
7
+ data.tar.gz: 681467aa0759581e4410d1524ce7c67e6c0fc1148cb736417d057478d2b28910dbc7a50c850e6caa9bbf8efcfb881267724361aabf23369286494a660d5d107f
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format documentation
3
+ --require "spec_helper"
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lawyer.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 John Cinnamond
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,141 @@
1
+ # Lawyer
2
+
3
+ Strong Duck Typing for Ruby.
4
+
5
+ Lawyer allows you to create contracts that specify how an object behaves.
6
+
7
+ require 'lawyer'
8
+
9
+ class Pingable < Lawyer::Contract
10
+ confirm :ping
11
+ end
12
+
13
+ You can then ensure that your class implements the contract:
14
+
15
+ require 'pingable'
16
+
17
+ class Foo
18
+ def ping
19
+ puts "ping"
20
+ end
21
+
22
+ def pong
23
+ puts "pong"
24
+ end
25
+ end
26
+
27
+ Foo.implements(Pingable)
28
+
29
+ ...but this works best when you write loosely coupled objects and then define the
30
+ interfaces between them. You can then write specs to check that a class implements
31
+ a particular contract:
32
+
33
+ require 'foo'
34
+ require 'pingable'
35
+
36
+ describe Foo do
37
+ it { should implement(Pingable) }
38
+ end
39
+
40
+ ...and use mocks to test methods that expect to receive objects that conform to
41
+ a particular contract:
42
+
43
+ describe Pinger do
44
+ let(:pingable) { contract_double(Pingable) }
45
+ subject(:pinger) { Pinger.new(pingable) }
46
+
47
+ it "pings the pingable" do
48
+ subject.run
49
+ expect(:pingable).to have_received(:ping)
50
+ end
51
+
52
+ it "can't call methods that aren't part of the contract" do
53
+ expect { pingable.pong }.to raise_error(NoMethodError)
54
+ end
55
+ end
56
+
57
+ ...all based off a single definition of the contract.
58
+
59
+ This helps you to write loosely coupled code that relies on well defined interfaces.
60
+ By declaring the contract up front and then using that in your tests you can ensure
61
+ that any mismatches between the expected interface and the actual impelmentations are
62
+ caught as you modify your codebase.
63
+
64
+ ## Installation
65
+
66
+ Add this line to your application's Gemfile:
67
+
68
+ gem 'lawyer'
69
+
70
+ And then execute:
71
+
72
+ $ bundle
73
+
74
+ Or install it yourself as:
75
+
76
+ $ gem install laywer
77
+
78
+ ## Usage
79
+
80
+ First up, create a contract that specifies the methods available in an interface:
81
+
82
+ require 'lawyer'
83
+
84
+ module Contracts
85
+ class Person < Lawyer::Contract
86
+ check :name # check that the method exists
87
+ check :name= => 1 # check the method arity
88
+ check :rename => [:firstname, :lastname] # check required named parameters (ruby 2.1 only)
89
+ end
90
+ end
91
+
92
+
93
+ Add Laywer to your spec_helper:
94
+
95
+ require 'lawyer/rspec'
96
+
97
+ RSpec.configure do |config|
98
+ config.include Lawyer::RSpec::Matchers
99
+ config.include Lawyer::RSpec::ContractDouble
100
+
101
+ # ...
102
+ end
103
+
104
+ Test an implementation:
105
+
106
+ require 'contracts/person'
107
+ require 'person_record'
108
+
109
+ describe PersonRecord do
110
+ it { should implement(Contracts::Person) }
111
+
112
+ # test the implementation
113
+ end
114
+
115
+ And test a receiver:
116
+
117
+ require 'contracts/person'
118
+ require 'namer'
119
+
120
+ describe Namer do
121
+ let(:person) { contract_double(Contracts::Person) }
122
+ subject(:namer) { Namer.new(person) }
123
+
124
+ it "sets the name" do
125
+ expect(person).to receive(:name=).with("John Smith")
126
+ namer.set_name("John Smith")
127
+ end
128
+ end
129
+
130
+ ## Credits
131
+
132
+ Many thanks to Jakub Oboza (http://lambdacu.be) for suggesting an original
133
+ implementation of this idea and for discussing the motivations behind it.
134
+
135
+ ## Contributing
136
+
137
+ 1. Fork it ( http://github.com/jcinnamond/lawyer/fork )
138
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
139
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
140
+ 4. Push to the branch (`git push origin my-new-feature`)
141
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new('spec')
6
+
7
+ # If you want to make this the default task
8
+ task :default => :spec
data/lawyer.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'lawyer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "lawyer"
8
+ spec.version = Lawyer::VERSION
9
+ spec.authors = ["John Cinnamond"]
10
+ spec.email = ["jc@panagile.com"]
11
+ spec.summary = %q{Strong Duck Typing for Ruby}
12
+ spec.homepage = "http://github.com/jcinnamond/lawyer"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(spec)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.5"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rspec", "~> 2.14.1"
23
+ end
@@ -0,0 +1,38 @@
1
+ module Lawyer
2
+ class BrokenContract < StandardError
3
+ def initialize(subject, contract, violations)
4
+ @subject = subject.name
5
+ @contract = contract.name
6
+ @method_missing_violations = violations.select { |v| v.is_a?(MethodMissingViolation) }
7
+ @wrong_arity_violations = violations.select { |v| v.is_a?(WrongArityViolation) }
8
+ @wrong_signature_violations = violations.select { |v| v.is_a?(WrongSignatureViolation) }
9
+ end
10
+
11
+ def to_s
12
+ str = "#{@subject} does not implement <#{@contract}>\n"
13
+ str << explain_violations(@method_missing_violations, "missing")
14
+ str << "\n" if @method_missing_violations &&
15
+ (@wrong_arity_violations || @wrong_signature_violations)
16
+ str << explain_violations(@wrong_arity_violations, "with the wrong arity")
17
+ str << "\n" if (@method_missing_violations || @wrong_arity_violations) &&
18
+ @wrong_signature_violations
19
+ str << explain_violations(@wrong_signature_violations, "with the wrong signature")
20
+ str
21
+ end
22
+
23
+ def explain_violations(violations, type)
24
+ str = ""
25
+ if violations.any?
26
+ count = violations.count
27
+ str << "\t(#{count} #{methods(count)} #{type})\n"
28
+ str << violations.map(&:to_s).join("\n")
29
+ str << "\n"
30
+ end
31
+ str
32
+ end
33
+
34
+ def methods(count)
35
+ count == 1 ? "method" : "methods"
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,72 @@
1
+ require 'lawyer/method_missing_violation'
2
+ require 'lawyer/wrong_arity_violation'
3
+ require 'lawyer/wrong_signature_violation'
4
+
5
+ module Lawyer
6
+ class Clause
7
+ attr_reader :name
8
+
9
+ def initialize(params)
10
+ @arity = nil
11
+ @signature = nil
12
+
13
+ if params.is_a?(Hash)
14
+ (@name, details) = params.first
15
+ case details
16
+ when Fixnum
17
+ @arity = details
18
+ when Array
19
+ @signature = details
20
+ end
21
+ else
22
+ @name = params.to_sym
23
+ end
24
+ end
25
+
26
+ def check(subject)
27
+ if missing_method?(subject)
28
+ Lawyer::MethodMissingViolation.new(@name)
29
+ elsif wrong_arity?(subject)
30
+ Lawyer::WrongArityViolation.new(@name, expected: @arity, actual: actual_arity(subject))
31
+ elsif wrong_signature?(subject)
32
+ Lawyer::WrongSignatureViolation.new(@name,
33
+ missing: missing_parameters(subject),
34
+ extra: extra_parameters(subject))
35
+ else
36
+ nil
37
+ end
38
+ end
39
+
40
+ def missing_method?(subject)
41
+ !subject.instance_methods.include?(@name)
42
+ end
43
+
44
+ def wrong_arity?(subject)
45
+ @arity && @arity != actual_arity(subject)
46
+ end
47
+
48
+ def actual_arity(subject)
49
+ method_from(subject).arity
50
+ end
51
+
52
+ def wrong_signature?(subject)
53
+ @signature && (missing_parameters(subject).any? || extra_parameters(subject).any?)
54
+ end
55
+
56
+ def missing_parameters(subject)
57
+ @signature - actual_signature(subject)
58
+ end
59
+
60
+ def extra_parameters(subject)
61
+ actual_signature(subject) - @signature
62
+ end
63
+
64
+ def actual_signature(subject)
65
+ method_from(subject).parameters.select { |p| p[0] == :keyreq }.map(&:last) || []
66
+ end
67
+
68
+ def method_from(subject)
69
+ subject.instance_method(@name)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,28 @@
1
+ require 'lawyer/clause'
2
+
3
+ module Lawyer
4
+ class Contract
5
+ class << self
6
+ def clauses
7
+ @clauses ||= []
8
+ end
9
+
10
+ def confirm(clause)
11
+ self.clauses << Lawyer::Clause.new(clause)
12
+ end
13
+
14
+ def check!(subject)
15
+ klass = subject.is_a?(Class) ? subject : subject.class
16
+
17
+ violations = self.clauses.map do |clause|
18
+ clause.check(klass)
19
+ end
20
+ violations.compact!
21
+
22
+ if violations.any?
23
+ raise Lawyer::BrokenContract.new(klass, self, violations)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ module Lawyer
2
+ class MethodMissingViolation
3
+ def initialize(name)
4
+ @name = name
5
+ end
6
+
7
+ def to_s
8
+ "\t[missing] #{@name}"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module Lawyer
2
+ module RSpec
3
+ module ContractDouble
4
+ def contract_double(contract)
5
+ methods = {}
6
+ contract.clauses.each do |clause|
7
+ methods[clause.name] = true
8
+ end
9
+ double(contract.name, methods)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ require 'rspec/expectations'
2
+
3
+ module Lawyer
4
+ module RSpec
5
+ module Matchers
6
+ extend ::RSpec::Matchers::DSL
7
+
8
+ matcher :implement do |contract|
9
+ match do |implementation|
10
+ begin
11
+ contract.check!(implementation)
12
+ true
13
+ rescue Lawyer::BrokenContract => e
14
+ @exception = e
15
+ false
16
+ end
17
+ end
18
+
19
+ failure_message_for_should do |actual|
20
+ @expectation.to_s
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,2 @@
1
+ require 'lawyer/rspec/matchers'
2
+ require 'lawyer/rspec/contract_double'
@@ -0,0 +1,3 @@
1
+ module Lawyer
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,13 @@
1
+ module Lawyer
2
+ class WrongArityViolation
3
+ def initialize(name, expected:, actual:)
4
+ @name = name
5
+ @expected = expected
6
+ @actual = actual
7
+ end
8
+
9
+ def to_s
10
+ "\t[wrong arity] #{@name} (takes #{@actual}, requires #{@expected})"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ module Lawyer
2
+ class WrongSignatureViolation
3
+ def initialize(name, missing:, extra:)
4
+ @name = name
5
+ @missing = missing
6
+ @extra = extra
7
+ end
8
+
9
+ def to_s
10
+ details = []
11
+ details << "missing #{@missing}" if @missing.any?
12
+ details << "extra #{@extra}" if @extra.any?
13
+ "\t[wrong signature] #{@name} (#{details.join(', ')})"
14
+ end
15
+ end
16
+ end
data/lib/lawyer.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'lawyer/version'
2
+ require 'lawyer/contract'
3
+ require 'lawyer/broken_contract'
4
+
5
+ require 'monkey_patch/module'
6
+
7
+ module Lawyer
8
+ end
@@ -0,0 +1,5 @@
1
+ class Module
2
+ def implements(contract)
3
+ contract.check!(self)
4
+ end
5
+ end
@@ -0,0 +1,73 @@
1
+ class TestContract < Lawyer::Contract
2
+ confirm :ping
3
+ confirm :pong => 2
4
+ confirm :pung => [:name, :size]
5
+ end
6
+
7
+ describe TestContract do
8
+ before :each do
9
+ # Stop modifications to the TestObject from leaking into other specs.
10
+ Object.send(:remove_const, :TestObject) if Object.const_defined?(:TestObject)
11
+ class TestObject;
12
+ def pong(a1); end
13
+ def pung(name:, hats:); end
14
+ end
15
+ end
16
+
17
+ describe "#check!" do
18
+ context "with a compliant object" do
19
+ before :each do
20
+ # Reopen the class and define the required methods
21
+ class TestObject;
22
+ def ping; end
23
+ def pong(a1, a2); end
24
+ def pung(name:, size:); end
25
+ end
26
+ end
27
+
28
+ it "does not raise an exception when checking a class" do
29
+ expect { TestContract.check!(TestObject) }.not_to raise_error
30
+ end
31
+
32
+ it "does not raise an exception when checking an object" do
33
+ expect { TestContract.check!(TestObject.new) }.not_to raise_error
34
+ end
35
+ end
36
+
37
+ context "with a non-compliant object" do
38
+ it "raises a BrokenContract exception when checking a class" do
39
+ expect { TestContract.check!(TestObject) }.to raise_error(Lawyer::BrokenContract)
40
+ end
41
+
42
+ it "raises a BrokenContract exception when checking an object" do
43
+ expect { TestContract.check!(TestObject.new) }.to raise_error(Lawyer::BrokenContract)
44
+ end
45
+
46
+ describe "the exception" do
47
+ before :each do
48
+ begin
49
+ TestContract.check!(TestObject)
50
+ rescue Lawyer::BrokenContract => e
51
+ @exception = e
52
+ end
53
+ end
54
+
55
+ it "includes the offending class and contract" do
56
+ expect(@exception.to_s).to include("TestObject does not implement <TestContract>\n")
57
+ end
58
+
59
+ it "includes the missing method details in the exception" do
60
+ expect(@exception.to_s).to include("\t(1 method missing)\n\t[missing] ping\n")
61
+ end
62
+
63
+ it "includes the incorrect arity details in the exception" do
64
+ expect(@exception.to_s).to include("\t(1 method with the wrong arity)\n\t[wrong arity] pong (takes 1, requires 2)\n")
65
+ end
66
+
67
+ it "includes required argument mismatch details in the exception" do
68
+ expect(@exception.to_s).to include("\t(1 method with the wrong signature)\n\t[wrong signature] pung (missing [:size], extra [:hats])\n")
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,15 @@
1
+ require 'lawyer/rspec'
2
+
3
+ class DoublableContract < Lawyer::Contract
4
+ confirm :ping
5
+ end
6
+
7
+ describe Lawyer::RSpec::ContractDouble do
8
+ include Lawyer::RSpec::ContractDouble
9
+
10
+ subject { contract_double(DoublableContract) }
11
+
12
+ it { should be_a(RSpec::Mocks::Mock) }
13
+ it { should respond_to(:ping) }
14
+ it { should_not respond_to(:pong) }
15
+ end
@@ -0,0 +1,28 @@
1
+ require 'lawyer/rspec'
2
+
3
+ describe Lawyer::RSpec::Matchers do
4
+ include Lawyer::RSpec::Matchers
5
+ let(:subject) { double("Module", name: "Module") }
6
+ let(:contract) { double("contract", check!: true, name: "Contract") }
7
+
8
+ it "defines 'implement'" do
9
+ expect(subject).to implement(contract)
10
+ end
11
+
12
+ it "calls checks the subject against the contract" do
13
+ expect(contract).to receive(:check!).with(subject)
14
+ expect(subject).to implement(contract)
15
+ end
16
+
17
+ context "with violations" do
18
+ let(:broken_contract) { Lawyer::BrokenContract.new(subject, contract, []) }
19
+
20
+ before :each do
21
+ allow(contract).to receive(:check!).and_raise(broken_contract)
22
+ end
23
+
24
+ it "fails the matcher" do
25
+ expect(subject).not_to implement(contract)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ describe Module do
2
+ describe "#implements" do
3
+ it "checks the module against the contract" do
4
+ class A; end
5
+
6
+ contract = double("contract")
7
+ expect(contract).to receive(:check!).with(A)
8
+ A.implements(contract)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ require 'lawyer'
2
+
3
+ RSpec.configure do |config|
4
+ config.treat_symbols_as_metadata_keys_with_true_values = true
5
+ config.run_all_when_everything_filtered = true
6
+ config.filter_run :focus
7
+
8
+ config.order = 'random'
9
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lawyer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - John Cinnamond
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.14.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.14.1
55
+ description:
56
+ email:
57
+ - jc@panagile.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - lawyer.gemspec
69
+ - lib/lawyer.rb
70
+ - lib/lawyer/broken_contract.rb
71
+ - lib/lawyer/clause.rb
72
+ - lib/lawyer/contract.rb
73
+ - lib/lawyer/method_missing_violation.rb
74
+ - lib/lawyer/rspec.rb
75
+ - lib/lawyer/rspec/contract_double.rb
76
+ - lib/lawyer/rspec/matchers.rb
77
+ - lib/lawyer/version.rb
78
+ - lib/lawyer/wrong_arity_violation.rb
79
+ - lib/lawyer/wrong_signature_violation.rb
80
+ - lib/monkey_patch/module.rb
81
+ - spec/lib/lawyer/contract_spec.rb
82
+ - spec/lib/lawyer/rspec/contract_double_spec.rb
83
+ - spec/lib/lawyer/rspec/matchers_spec.rb
84
+ - spec/module_spec.rb
85
+ - spec/spec_helper.rb
86
+ homepage: http://github.com/jcinnamond/lawyer
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.2.0
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Strong Duck Typing for Ruby
110
+ test_files:
111
+ - spec/lib/lawyer/contract_spec.rb
112
+ - spec/lib/lawyer/rspec/contract_double_spec.rb
113
+ - spec/lib/lawyer/rspec/matchers_spec.rb
114
+ - spec/module_spec.rb
115
+ - spec/spec_helper.rb