wepredict 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,11 +1,11 @@
1
1
  source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
2
+
3
+ gem "thor", "~> 0.14.6"
4
+ gem "yajl-ruby", "~> 0.8.3"
5
5
 
6
6
  # Add dependencies to develop your gem here.
7
- # Include everything needed to run rake, tests, features, etc.
8
7
  group :development do
8
+ gem "rdoc", "~> 3.9.4"
9
9
  gem "rspec", "~> 2.6.0"
10
10
  gem "bundler", "~> 1.0.0"
11
11
  gem "jeweler", "~> 1.6.4"
data/Gemfile.lock CHANGED
@@ -8,6 +8,7 @@ GEM
8
8
  git (>= 1.2.5)
9
9
  rake
10
10
  rake (0.9.2)
11
+ rdoc (3.9.4)
11
12
  rspec (2.6.0)
12
13
  rspec-core (~> 2.6.0)
13
14
  rspec-expectations (~> 2.6.0)
@@ -16,6 +17,8 @@ GEM
16
17
  rspec-expectations (2.6.0)
17
18
  diff-lcs (~> 1.1.2)
18
19
  rspec-mocks (2.6.0)
20
+ thor (0.14.6)
21
+ yajl-ruby (0.8.3)
19
22
 
20
23
  PLATFORMS
21
24
  ruby
@@ -23,4 +26,7 @@ PLATFORMS
23
26
  DEPENDENCIES
24
27
  bundler (~> 1.0.0)
25
28
  jeweler (~> 1.6.4)
29
+ rdoc (~> 3.9.4)
26
30
  rspec (~> 2.6.0)
31
+ thor (~> 0.14.6)
32
+ yajl-ruby (~> 0.8.3)
data/Rakefile CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'bundler'
5
+
5
6
  begin
6
7
  Bundler.setup(:default, :development)
7
8
  rescue Bundler::BundlerError => e
@@ -9,6 +10,7 @@ rescue Bundler::BundlerError => e
9
10
  $stderr.puts "Run `bundle install` to install missing gems"
10
11
  exit e.status_code
11
12
  end
13
+
12
14
  require 'rake'
13
15
 
14
16
  require 'jeweler'
@@ -21,21 +23,17 @@ Jeweler::Tasks.new do |gem|
21
23
  gem.description = %Q{Provides easy access to the WePredict data mining API}
22
24
  gem.email = "ben@benmcredmond.com"
23
25
  gem.authors = ["Ben McRedmond"]
26
+ gem.executables = ["wepredict"]
24
27
  # dependencies defined in Gemfile
25
28
  end
26
29
  Jeweler::RubygemsDotOrgTasks.new
27
30
 
28
- require 'rake/testtask'
29
- Rake::TestTask.new(:test) do |test|
30
- test.libs << 'lib' << 'test'
31
- test.pattern = 'test/**/test_*.rb'
32
- test.verbose = true
33
- end
34
-
35
- task :default => :test
31
+ require 'rspec/core/rake_task'
32
+ RSpec::Core::RakeTask.new
33
+ task :default => :spec
36
34
 
37
35
  require 'rdoc/task'
38
- Rake::RDocTask.new do |rdoc|
36
+ RDoc::Task.new do |rdoc|
39
37
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
38
 
41
39
  rdoc.rdoc_dir = 'rdoc'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/bin/wepredict ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if ENV['WP_DEV']
4
+ base = File.expand_path(File.dirname(File.dirname(__FILE__)))
5
+ $:.push("#{base}/lib/")
6
+ end
7
+
8
+ require "wepredict/cli"
9
+ WePredict::CLI::CLI.start
@@ -0,0 +1,55 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'yajl'
4
+
5
+ require 'wepredict/exceptions'
6
+
7
+ module WePredict
8
+ class API
9
+
10
+ @@endpoint = URI.parse((ENV["WP_DEV"]) ? "http://wepredict.dev/api/" : "http://demo.wepredictapp.com/api/")
11
+
12
+ # Makes a request to the WePredict API if the API
13
+ # encounters an error, a WePredictError is raised
14
+ # containing the error message and the response body
15
+ def self.make_request(method, params)
16
+ res = Net::HTTP.start(@@endpoint.host, @@endpoint.port) do |h|
17
+ query_string = params.map {|k,v| "#{k}=#{v}"}.join('&')
18
+ h.get("#{@@endpoint.path}#{method}?#{URI.escape(query_string)}")
19
+ end
20
+
21
+ json = Yajl::Parser.parse(res.body, :symbolize_keys => true)
22
+ if(json.kind_of?(Hash) && json[:state] == 'error')
23
+ ex = case json[:code]
24
+ when 400
25
+ Errors::BadRequest
26
+ when 403
27
+ Errors::AccessDenied
28
+ end
29
+
30
+ raise ex.new(json), json[:message]
31
+ end
32
+
33
+ json
34
+ end
35
+
36
+ # @@endpoint accessor
37
+ def self.endpoint
38
+ @@endpoint
39
+ end
40
+
41
+ protected
42
+ # Checks the correct paramaters were passed to a method
43
+ def self.params?(params, required)
44
+ required.each do |r|
45
+ raise ArgumentError, "Paramater, #{r}, is missing" if params[r].nil?
46
+ end
47
+ end
48
+
49
+ def self.class_name
50
+ n = self.name.split('::').last.scan(/[A-Z][^A-Z]*/)
51
+ n.map {|o| o.downcase}.join('_')
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,24 @@
1
+ module WePredict
2
+ module Classifiers
3
+ class Classifier < API
4
+
5
+ def initialize
6
+ @api_key = Classifier.api_key
7
+ end
8
+
9
+ def self.classify(options)
10
+ params? options, [:text]
11
+ make_request("classifiers/#{self.class_name}/classify", options.merge(:api_key => self.api_key))
12
+ end
13
+
14
+ def self.api_key
15
+ f = File.open(File.expand_path("~/.wepredict"), 'r')
16
+ k = f.read(32)
17
+ f.close
18
+
19
+ k
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,6 @@
1
+ module WePredict
2
+ module Classifiers
3
+ class Sentiment < Classifier
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,155 @@
1
+ require 'thor'
2
+ require 'wepredict/user'
3
+
4
+ module WePredict
5
+ module CLI
6
+ class User < Thor
7
+
8
+ include Thor::Actions
9
+
10
+ desc "signup EMAIL", "Signup for WePredict"
11
+ def signup(email)
12
+ begin
13
+ password = capture_password(true)
14
+ u = WePredict::User.create(:email => email, :password => password)
15
+ rescue WePredict::Errors::BadRequest => e
16
+ if(e.body[:error] == "user_exists")
17
+ say "User already exists, maybe try logging in?", :red
18
+ exit
19
+ end
20
+
21
+ say e.message, :red
22
+ retry
23
+ end
24
+
25
+ say "\nThankyou for signing up for WePredict", :green
26
+ write_api_key(u[:api_key])
27
+ end
28
+
29
+ desc "login EMAIL", "Login to your WePredict account (will save API key in ~/.wepredict)"
30
+ def login(email)
31
+ password = capture_password
32
+ begin
33
+ u = WePredict::User.get(:email => email, :password => password)
34
+ rescue WePredict::Errors::AccessDenied => e
35
+ say e.message, :red
36
+ retry
37
+ end
38
+
39
+ write_api_key(u[:api_key])
40
+ end
41
+
42
+ desc "delete EMAIl", "Delete your WePredict account"
43
+ def delete(email)
44
+ password = capture_password
45
+ confirm = yes?("Are you sure you want to close your account? This is non-reversable (y/n):")
46
+
47
+ if !confirm
48
+ say "Phew, almost lost you there!"
49
+ exit
50
+ end
51
+
52
+ begin
53
+ WePredict::User.delete(:email => email, :password => password)
54
+ rescue WePredict::Errors::AccessDenied => e
55
+ say e.message, :red
56
+ retry
57
+ end
58
+
59
+ say "Sucessfully closed your WePredict account", :green
60
+ end
61
+
62
+ desc "change_password EMAIL", "Change the password for your WePredict account"
63
+ def change_password(email)
64
+ password = authenticate(email)
65
+ new_password = capture_password(true)
66
+ WePredict::User.change_password(:email => email, :password => password, :new_password => new_password)
67
+
68
+ say "Sucessfully changed your password", :green
69
+ end
70
+
71
+ desc "change_email EMAIL NEW_EMAIL", "Change your EMAIL to NEW_EMAIL"
72
+ def change_email(email, new_email)
73
+ password = authenticate(email)
74
+ WePredict::User.change_email(:email => email, :password => password, :new_email => email)
75
+
76
+ say "Sucessfully changed your email address", :green
77
+ end
78
+
79
+ desc "forgotten_password EMAIL", "Reset your password"
80
+ def forgotten_password(email)
81
+ begin
82
+ WePredict::User.forgotten_password(:email => email)
83
+ rescue WePredict::Errors::BadRequest
84
+ say "We can't find you! Maybe you want to signup instead?", :red
85
+ exit
86
+ end
87
+
88
+ say "We have sent you a super secret code to your email, go check your email and then enter the code here!"
89
+ begin
90
+ code = ask "Super secret code:"
91
+ password = capture_password(true)
92
+ WePredict::User.reset_forgotten_password(:email => email, :forgotten_password_code => code, :new_password => password)
93
+ rescue WePredict::Errors::AccessDenied
94
+ say "That's not the right super secret code! Try again", :red
95
+ retry
96
+ end
97
+
98
+ say "Sucessfully reset your password", :green
99
+ end
100
+
101
+ def self.banner(task, namespace = true, subcommand = false)
102
+ "#{basename} #{self.name.split('::').last.downcase} #{task.formatted_usage(self, false, subcommand)}"
103
+ end
104
+
105
+ private
106
+ def authenticate(email)
107
+ begin
108
+ password = capture_password
109
+ WePredict::User.get(:email => email, :password => password)
110
+ rescue WePredict::Errors::AccessDenied => e
111
+ say e.message, :red
112
+ retry
113
+ end
114
+
115
+ password
116
+ end
117
+
118
+ def write_api_key(api_key)
119
+ f = File.open(File.expand_path("~/.wepredict"), 'w')
120
+ f.write api_key
121
+ f.close
122
+
123
+ say "Your api key has been saved in ~/.wepredict", :green
124
+ end
125
+
126
+ def capture_password(new_password = false)
127
+ begin
128
+ system("stty -echo")
129
+
130
+ password = ask((new_password) ? "Please enter a password (>= 6 chars):" : "Password:")
131
+ print "\n"
132
+
133
+ raise ArgumentError if(password.length < 6)
134
+ raise RuntimeError if(new_password && password != ask("Please confirm your password:"))
135
+ rescue ArgumentError
136
+ print "\n"
137
+ say "Password is too short, please try again", :red
138
+
139
+ retry
140
+ rescue RuntimeError
141
+ print "\n\n"
142
+ say "Passwords don't match, please try again", :red
143
+
144
+ retry
145
+ ensure
146
+ system("stty echo")
147
+ print "\n"
148
+ end
149
+
150
+ password
151
+ end
152
+
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,14 @@
1
+ require 'thor'
2
+ require 'thor/group'
3
+
4
+ require 'wepredict/cli/user'
5
+
6
+ module WePredict
7
+ module CLI
8
+ class CLI < Thor
9
+
10
+ register WePredict::CLI::User, :user, "user", "Commands for interacting with a user"
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module WePredict
2
+ module Errors
3
+
4
+ class APIError < StandardError
5
+ attr_reader :body
6
+
7
+ def initialize(body)
8
+ @body = body
9
+ end
10
+ end
11
+
12
+ class BadRequest < APIError; end
13
+ class AccessDenied < APIError; end
14
+
15
+ end
16
+ end
@@ -0,0 +1,37 @@
1
+ require 'wepredict/api'
2
+
3
+ module WePredict
4
+ class User < API
5
+
6
+ @@methods_and_required_params = {:create => [:email, :password],
7
+ :get => [:email, :password],
8
+ :new_api_key => [:email, :password],
9
+ :change_password => [:email, :password, :new_password],
10
+ :change_email => [:email, :password, :new_email],
11
+ :delete => [:email, :password],
12
+ :forgotten_password => [:email],
13
+ :reset_forgotten_password => [:email, :forgotten_password_code, :new_password]}
14
+
15
+ # Implements method calles for all the methods defined
16
+ # in @@methods_and_required_params which is intuitively
17
+ # a map of method names to their required paramaters.
18
+ def self.method_missing(method_name, *args, &block)
19
+ if(respond_to?(method_name))
20
+ params? *args, @@methods_and_required_params[method_name]
21
+
22
+ method_name = "#{class_name.downcase}/#{method_name}"
23
+
24
+ make_request(method_name, *args)
25
+ else
26
+ super
27
+ end
28
+ end
29
+
30
+ # Implements correct respond_to? behaviour for
31
+ # methods defined through method_missing
32
+ def self.respond_to?(method_name)
33
+ !!@@methods_and_required_params[method_name] || super
34
+ end
35
+
36
+ end
37
+ end
data/lib/wepredict.rb CHANGED
@@ -0,0 +1,7 @@
1
+ require 'bundler/setup'
2
+
3
+ require "wepredict/api"
4
+ require "wepredict/classifier"
5
+ require "wepredict/classifiers/sentiment"
6
+ require "wepredict/exceptions"
7
+ require "wepredict/user"
@@ -0,0 +1,28 @@
1
+ require './lib/wepredict/user'
2
+
3
+ module WePredict
4
+ describe User do
5
+
6
+ # All the other user methods are implemented
7
+ # in the same way (through method_missing), so,
8
+ # we only test one.
9
+ describe "#create" do
10
+ it "fails if you don't provide an :email and :password" do
11
+ expect {
12
+ User.create(:email => "ben@example.com")
13
+ }.to raise_error(ArgumentError, /missing/)
14
+
15
+ expect {
16
+ User.create(:password => "super secret sauce")
17
+ }.to raise_error(ArgumentError, /missing/)
18
+ end
19
+
20
+ it "sends an api request to create a user" do
21
+ u = {:email => "ben@example.com", :password => "super secret sauce"}
22
+ User.should_receive(:make_request).with('user/create', u).and_return(true)
23
+ User.create(u)
24
+ end
25
+ end
26
+
27
+ end
28
+ end
data/wepredict.gemspec ADDED
@@ -0,0 +1,72 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{wepredict}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{Ben McRedmond}]
12
+ s.date = %q{2011-09-06}
13
+ s.description = %q{Provides easy access to the WePredict data mining API}
14
+ s.email = %q{ben@benmcredmond.com}
15
+ s.executables = [%q{wepredict}]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/wepredict",
28
+ "lib/wepredict.rb",
29
+ "lib/wepredict/api.rb",
30
+ "lib/wepredict/classifier.rb",
31
+ "lib/wepredict/classifiers/sentiment.rb",
32
+ "lib/wepredict/cli.rb",
33
+ "lib/wepredict/cli/user.rb",
34
+ "lib/wepredict/exceptions.rb",
35
+ "lib/wepredict/user.rb",
36
+ "spec/wepredict/user_spec.rb",
37
+ "wepredict.gemspec"
38
+ ]
39
+ s.homepage = %q{http://github.com/benofsky/WePredict-Client}
40
+ s.licenses = [%q{MIT}]
41
+ s.require_paths = [%q{lib}]
42
+ s.rubygems_version = %q{1.8.7}
43
+ s.summary = %q{Client gem for WePredict}
44
+
45
+ if s.respond_to? :specification_version then
46
+ s.specification_version = 3
47
+
48
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49
+ s.add_runtime_dependency(%q<thor>, ["~> 0.14.6"])
50
+ s.add_runtime_dependency(%q<yajl-ruby>, ["~> 0.8.3"])
51
+ s.add_development_dependency(%q<rdoc>, ["~> 3.9.4"])
52
+ s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
53
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
54
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
55
+ else
56
+ s.add_dependency(%q<thor>, ["~> 0.14.6"])
57
+ s.add_dependency(%q<yajl-ruby>, ["~> 0.8.3"])
58
+ s.add_dependency(%q<rdoc>, ["~> 3.9.4"])
59
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
60
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
61
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<thor>, ["~> 0.14.6"])
65
+ s.add_dependency(%q<yajl-ruby>, ["~> 0.8.3"])
66
+ s.add_dependency(%q<rdoc>, ["~> 3.9.4"])
67
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
68
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
69
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
70
+ end
71
+ end
72
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wepredict
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,44 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-03 00:00:00.000000000Z
12
+ date: 2011-09-06 00:00:00.000000000Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: &70118865907720 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.14.6
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70118865907720
25
+ - !ruby/object:Gem::Dependency
26
+ name: yajl-ruby
27
+ requirement: &70118865904580 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.8.3
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70118865904580
36
+ - !ruby/object:Gem::Dependency
37
+ name: rdoc
38
+ requirement: &70118865900420 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 3.9.4
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70118865900420
14
47
  - !ruby/object:Gem::Dependency
15
48
  name: rspec
16
- requirement: &70260187847580 !ruby/object:Gem::Requirement
49
+ requirement: &70118865899580 !ruby/object:Gem::Requirement
17
50
  none: false
18
51
  requirements:
19
52
  - - ~>
@@ -21,10 +54,10 @@ dependencies:
21
54
  version: 2.6.0
22
55
  type: :development
23
56
  prerelease: false
24
- version_requirements: *70260187847580
57
+ version_requirements: *70118865899580
25
58
  - !ruby/object:Gem::Dependency
26
59
  name: bundler
27
- requirement: &70260187845460 !ruby/object:Gem::Requirement
60
+ requirement: &70118865897720 !ruby/object:Gem::Requirement
28
61
  none: false
29
62
  requirements:
30
63
  - - ~>
@@ -32,10 +65,10 @@ dependencies:
32
65
  version: 1.0.0
33
66
  type: :development
34
67
  prerelease: false
35
- version_requirements: *70260187845460
68
+ version_requirements: *70118865897720
36
69
  - !ruby/object:Gem::Dependency
37
70
  name: jeweler
38
- requirement: &70260187843700 !ruby/object:Gem::Requirement
71
+ requirement: &70118865896340 !ruby/object:Gem::Requirement
39
72
  none: false
40
73
  requirements:
41
74
  - - ~>
@@ -43,10 +76,11 @@ dependencies:
43
76
  version: 1.6.4
44
77
  type: :development
45
78
  prerelease: false
46
- version_requirements: *70260187843700
79
+ version_requirements: *70118865896340
47
80
  description: Provides easy access to the WePredict data mining API
48
81
  email: ben@benmcredmond.com
49
- executables: []
82
+ executables:
83
+ - wepredict
50
84
  extensions: []
51
85
  extra_rdoc_files:
52
86
  - LICENSE.txt
@@ -58,9 +92,17 @@ files:
58
92
  - README.rdoc
59
93
  - Rakefile
60
94
  - VERSION
95
+ - bin/wepredict
61
96
  - lib/wepredict.rb
62
- - test/helper.rb
63
- - test/test_wepredict.rb
97
+ - lib/wepredict/api.rb
98
+ - lib/wepredict/classifier.rb
99
+ - lib/wepredict/classifiers/sentiment.rb
100
+ - lib/wepredict/cli.rb
101
+ - lib/wepredict/cli/user.rb
102
+ - lib/wepredict/exceptions.rb
103
+ - lib/wepredict/user.rb
104
+ - spec/wepredict/user_spec.rb
105
+ - wepredict.gemspec
64
106
  homepage: http://github.com/benofsky/WePredict-Client
65
107
  licenses:
66
108
  - MIT
@@ -76,7 +118,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
76
118
  version: '0'
77
119
  segments:
78
120
  - 0
79
- hash: -3889679430223307924
121
+ hash: 3624294656438796082
80
122
  required_rubygems_version: !ruby/object:Gem::Requirement
81
123
  none: false
82
124
  requirements:
data/test/helper.rb DELETED
@@ -1,18 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler'
3
- begin
4
- Bundler.setup(:default, :development)
5
- rescue Bundler::BundlerError => e
6
- $stderr.puts e.message
7
- $stderr.puts "Run `bundle install` to install missing gems"
8
- exit e.status_code
9
- end
10
- require 'test/unit'
11
- require 'shoulda'
12
-
13
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
- $LOAD_PATH.unshift(File.dirname(__FILE__))
15
- require 'wepredict'
16
-
17
- class Test::Unit::TestCase
18
- end
@@ -1,7 +0,0 @@
1
- require 'helper'
2
-
3
- class TestWepredict < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
6
- end
7
- end