exercism 0.0.18 → 0.0.19
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/exercism.gemspec +1 -1
- data/lib/cli.rb +39 -19
- data/lib/exercism.rb +20 -14
- data/lib/exercism/assignment.rb +5 -1
- data/lib/exercism/config.rb +29 -4
- data/lib/exercism/env.rb +21 -0
- data/lib/exercism/submission.rb +28 -0
- data/lib/exercism/version.rb +1 -1
- data/test/exercism/config_test.rb +32 -21
- data/test/exercism/submission_test.rb +28 -0
- data/test/exercism_test.rb +3 -11
- metadata +22 -2
data/exercism.gemspec
CHANGED
|
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
19
|
spec.require_paths = ["lib"]
|
|
20
20
|
|
|
21
|
+
spec.add_dependency "json"
|
|
21
22
|
spec.add_dependency "faraday"
|
|
22
23
|
spec.add_dependency "thor"
|
|
23
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
|
@@ -28,7 +29,6 @@ Gem::Specification.new do |spec|
|
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
if RUBY_VERSION <= "1.8.7"
|
|
31
|
-
spec.add_dependency "json"
|
|
32
32
|
spec.add_development_dependency "nokogiri", "~>1.5.0"
|
|
33
33
|
else
|
|
34
34
|
spec.add_development_dependency "nokogiri", "~>1.6.0"
|
data/lib/cli.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'rubygems' if RUBY_VERSION == '1.8.7'
|
|
1
2
|
require 'thor'
|
|
2
3
|
|
|
3
4
|
class Exercism
|
|
@@ -50,12 +51,22 @@ class Exercism
|
|
|
50
51
|
def submit(file)
|
|
51
52
|
require 'exercism'
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
submission = Submission.new(file)
|
|
55
|
+
|
|
56
|
+
if submission.test?
|
|
57
|
+
say "It looks like this is a test, you probably don't want to do that."
|
|
58
|
+
if no?("Do you want to submit it anyway? [y/n]")
|
|
59
|
+
return
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
54
63
|
begin
|
|
55
|
-
response = Exercism::Api.new(options[:host], Exercism.user).submit(file)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
64
|
+
response = Exercism::Api.new(options[:host], Exercism.user).submit(submission.file)
|
|
65
|
+
say "Your assignment has been submitted."
|
|
66
|
+
|
|
67
|
+
body = JSON.parse(response.body)
|
|
68
|
+
url = "#{options[:host]}/#{Exercism.user.github_username}/#{body['language']}/#{body['exercise']}"
|
|
69
|
+
say "For feedback on your submission visit #{url}"
|
|
59
70
|
rescue Exception => e
|
|
60
71
|
puts "There was an issue with your submission."
|
|
61
72
|
puts e.message
|
|
@@ -68,13 +79,24 @@ class Exercism
|
|
|
68
79
|
|
|
69
80
|
username = ask("Your GitHub username:")
|
|
70
81
|
key = ask("Your exercism.io API key:")
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
82
|
+
default_dir = FileUtils.pwd
|
|
83
|
+
say "What is your exercism exercises project path?"
|
|
84
|
+
say "Press Enter to select the default (#{default_dir}):\n"
|
|
85
|
+
dir = ask ">"
|
|
86
|
+
if dir.empty?
|
|
87
|
+
dir = default_dir
|
|
88
|
+
end
|
|
89
|
+
project_dir = File.expand_path(dir)
|
|
90
|
+
|
|
91
|
+
say "Where do you want your configuration stored? (type a number)"
|
|
92
|
+
say "1. #{File.join(Exercism.home, '.exercism')}"
|
|
93
|
+
say "2. #{File.join(Exercism.home, '.config', 'exercism')}"
|
|
94
|
+
|
|
95
|
+
if ask(">").to_i == 2
|
|
96
|
+
Exercism.login username, key, project_dir, File.join(Exercism.home, '.config')
|
|
97
|
+
else
|
|
98
|
+
Exercism.login username, key, project_dir, Exercism.home
|
|
75
99
|
end
|
|
76
|
-
path = File.expand_path(path)
|
|
77
|
-
Exercism.login(username, key, path)
|
|
78
100
|
|
|
79
101
|
say("Your credentials have been written to #{Exercism.config.file}")
|
|
80
102
|
end
|
|
@@ -95,22 +117,20 @@ class Exercism
|
|
|
95
117
|
puts "You are not logged in."
|
|
96
118
|
end
|
|
97
119
|
|
|
98
|
-
private
|
|
120
|
+
private
|
|
121
|
+
|
|
99
122
|
def api(host = options[:host])
|
|
100
123
|
Exercism::Api.new(host, Exercism.user, Exercism.project_dir)
|
|
101
124
|
end
|
|
102
125
|
|
|
103
|
-
def submission_url(response_body, host)
|
|
104
|
-
body = JSON.parse(response_body)
|
|
105
|
-
"#{host}/user/#{body['language']}/#{body['exercise']}"
|
|
106
|
-
end
|
|
107
|
-
|
|
108
126
|
def report(assignments)
|
|
109
127
|
if assignments.empty?
|
|
110
|
-
|
|
128
|
+
say "No assignments fetched."
|
|
111
129
|
else
|
|
112
130
|
assignments.each do |assignment|
|
|
113
|
-
|
|
131
|
+
say "\nFetched #{assignment.exercise}"
|
|
132
|
+
say File.join(assignment.exercise, 'README.md')
|
|
133
|
+
say File.join(assignment.exercise, assignment.test_file)
|
|
114
134
|
end
|
|
115
135
|
end
|
|
116
136
|
end
|
data/lib/exercism.rb
CHANGED
|
@@ -3,36 +3,35 @@ require 'etc'
|
|
|
3
3
|
require 'json'
|
|
4
4
|
require 'yaml'
|
|
5
5
|
require 'fileutils'
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
old_warn, $-w = $-w, nil
|
|
8
|
+
begin
|
|
9
|
+
require 'faraday'
|
|
10
|
+
ensure
|
|
11
|
+
$-w = old_warn
|
|
12
|
+
end
|
|
13
|
+
|
|
7
14
|
require 'exercism/version'
|
|
15
|
+
require 'exercism/env'
|
|
8
16
|
require 'exercism/config'
|
|
9
17
|
require 'exercism/user'
|
|
10
18
|
require 'exercism/assignment'
|
|
19
|
+
require 'exercism/submission'
|
|
11
20
|
require 'exercism/api'
|
|
12
21
|
|
|
13
22
|
class Exercism
|
|
14
23
|
|
|
15
24
|
def self.home
|
|
16
|
-
|
|
17
|
-
ENV["HOMEDRIVE"]+ENV["HOMEPATH"]
|
|
18
|
-
else
|
|
19
|
-
return File.expand_path('~') if RUBY_VERSION <= "1.8.7"
|
|
20
|
-
Dir.home(Etc.getlogin)
|
|
21
|
-
end
|
|
25
|
+
@home ||= Env.home
|
|
22
26
|
end
|
|
23
27
|
|
|
24
|
-
def self.login(github_username, key, dir)
|
|
28
|
+
def self.login(github_username, key, dir, config_path)
|
|
25
29
|
data = {
|
|
26
30
|
'github_username' => github_username,
|
|
27
31
|
'key' => key,
|
|
28
32
|
'project_dir' => dir
|
|
29
33
|
}
|
|
30
|
-
Config.write(
|
|
31
|
-
User.new(github_username, key)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def self.config
|
|
35
|
-
Config.read(home)
|
|
34
|
+
Config.write(config_path, data)
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
def self.user
|
|
@@ -44,4 +43,11 @@ class Exercism
|
|
|
44
43
|
config.project_dir
|
|
45
44
|
end
|
|
46
45
|
|
|
46
|
+
def self.alternate_config_path
|
|
47
|
+
Config.alternate_path
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.config
|
|
51
|
+
Config.read(home)
|
|
52
|
+
end
|
|
47
53
|
end
|
data/lib/exercism/assignment.rb
CHANGED
|
@@ -3,7 +3,7 @@ class Exercism
|
|
|
3
3
|
|
|
4
4
|
def self.save(data, path)
|
|
5
5
|
data['assignments'].map do |attributes|
|
|
6
|
-
|
|
6
|
+
new(attributes.merge('project_dir' => path)).save
|
|
7
7
|
end
|
|
8
8
|
end
|
|
9
9
|
|
|
@@ -18,6 +18,10 @@ class Exercism
|
|
|
18
18
|
@project_dir = attributes['project_dir']
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
def exercise
|
|
22
|
+
File.join(track, slug)
|
|
23
|
+
end
|
|
24
|
+
|
|
21
25
|
def save
|
|
22
26
|
FileUtils.mkdir_p assignment_dir
|
|
23
27
|
save_readme
|
data/lib/exercism/config.rb
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
class Exercism
|
|
2
2
|
class Config
|
|
3
3
|
|
|
4
|
+
def self.alternate_path
|
|
5
|
+
File.join(Env.home, '.config')
|
|
6
|
+
end
|
|
7
|
+
|
|
4
8
|
def self.read(path)
|
|
5
|
-
new(path)
|
|
9
|
+
config = new(path)
|
|
10
|
+
return config if config.exists?
|
|
11
|
+
|
|
12
|
+
new(alternate_path) unless config.exists?
|
|
6
13
|
end
|
|
7
14
|
|
|
8
15
|
def self.write(path, data)
|
|
@@ -13,11 +20,11 @@ class Exercism
|
|
|
13
20
|
config.save
|
|
14
21
|
end
|
|
15
22
|
|
|
16
|
-
attr_reader :
|
|
23
|
+
attr_reader :path
|
|
17
24
|
attr_writer :github_username, :key, :project_dir
|
|
18
25
|
|
|
19
26
|
def initialize(path)
|
|
20
|
-
@
|
|
27
|
+
@path = path
|
|
21
28
|
end
|
|
22
29
|
|
|
23
30
|
def github_username
|
|
@@ -34,6 +41,8 @@ class Exercism
|
|
|
34
41
|
|
|
35
42
|
def save
|
|
36
43
|
FileUtils.mkdir_p(project_dir)
|
|
44
|
+
FileUtils.mkdir_p(path)
|
|
45
|
+
|
|
37
46
|
File.open file, 'w' do |f|
|
|
38
47
|
data = {
|
|
39
48
|
'github_username' => github_username,
|
|
@@ -46,11 +55,27 @@ class Exercism
|
|
|
46
55
|
end
|
|
47
56
|
|
|
48
57
|
def delete
|
|
49
|
-
FileUtils.rm(file) if
|
|
58
|
+
FileUtils.rm(file) if exists?
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def exists?
|
|
62
|
+
File.exists?(file)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def file
|
|
66
|
+
@file ||= File.join(path, filename)
|
|
50
67
|
end
|
|
51
68
|
|
|
52
69
|
private
|
|
53
70
|
|
|
71
|
+
def filename
|
|
72
|
+
default? ? ".exercism" : "exercism"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def default?
|
|
76
|
+
path !~ /\.config/
|
|
77
|
+
end
|
|
78
|
+
|
|
54
79
|
def from_yaml
|
|
55
80
|
unless @data
|
|
56
81
|
@data = YAML.load(File.read(file))
|
data/lib/exercism/env.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class Exercism
|
|
2
|
+
class Env
|
|
3
|
+
def self.home
|
|
4
|
+
if windows_nt?
|
|
5
|
+
ENV["HOMEDRIVE"] + ENV["HOMEPATH"]
|
|
6
|
+
elsif ruby18?
|
|
7
|
+
File.expand_path('~')
|
|
8
|
+
else
|
|
9
|
+
Dir.home(Etc.getlogin)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.windows_nt?
|
|
14
|
+
ENV["OS"] == 'Windows_NT'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.ruby18?
|
|
18
|
+
RUBY_VERSION == '1.8.7'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class Exercism
|
|
2
|
+
class Submission
|
|
3
|
+
|
|
4
|
+
def self.test?(file)
|
|
5
|
+
new(file).test?
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
attr_reader :file
|
|
9
|
+
def initialize(file)
|
|
10
|
+
@file = file
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test?
|
|
14
|
+
test_identifiers.any? do |_, suffix|
|
|
15
|
+
file.end_with?(suffix)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_identifiers
|
|
20
|
+
{
|
|
21
|
+
:ruby => '_test.rb',
|
|
22
|
+
:js => '.spec.js',
|
|
23
|
+
:elixir => '_test.exs'
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/exercism/version.rb
CHANGED
|
@@ -6,8 +6,20 @@ class ConfigTest < Minitest::Test
|
|
|
6
6
|
'./test/fixtures'
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
+
def data
|
|
10
|
+
{
|
|
11
|
+
'github_username' => 'bob',
|
|
12
|
+
'key' => '7a7096c',
|
|
13
|
+
'project_dir' => '/tmp'
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
9
17
|
def key
|
|
10
|
-
'
|
|
18
|
+
data['key']
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def write_config_file(path, info = {})
|
|
22
|
+
Exercism::Config.write(path, data.merge!(info))
|
|
11
23
|
end
|
|
12
24
|
|
|
13
25
|
def teardown
|
|
@@ -15,6 +27,10 @@ class ConfigTest < Minitest::Test
|
|
|
15
27
|
FileUtils.rm('./test/fixtures/.exercism')
|
|
16
28
|
end
|
|
17
29
|
|
|
30
|
+
if File.exists?('./test/fixtures/.config/exercism')
|
|
31
|
+
FileUtils.rm_r('./test/fixtures/.config')
|
|
32
|
+
end
|
|
33
|
+
|
|
18
34
|
if File.exists?('./test/fixtures/some/project/dir')
|
|
19
35
|
FileUtils.rm_r('./test/fixtures/some')
|
|
20
36
|
end
|
|
@@ -27,39 +43,34 @@ class ConfigTest < Minitest::Test
|
|
|
27
43
|
assert_equal '/tmp', config.project_dir
|
|
28
44
|
end
|
|
29
45
|
|
|
46
|
+
def test_reads_from_alternate_path_config_file_when_default_is_missing
|
|
47
|
+
write_config_file('./test/fixtures/.config')
|
|
48
|
+
Exercism::Config.stub(:alternate_path, './test/fixtures/.config') do
|
|
49
|
+
config = Exercism::Config.read(path)
|
|
50
|
+
assert_equal 'bob', config.github_username
|
|
51
|
+
assert_equal key, config.key
|
|
52
|
+
assert_equal '/tmp', config.project_dir
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
30
56
|
def test_write_config_file
|
|
31
|
-
|
|
32
|
-
'github_username' => 'bob',
|
|
33
|
-
'key' => key,
|
|
34
|
-
'project_dir' => '/tmp'
|
|
35
|
-
}
|
|
36
|
-
config = Exercism::Config.write(path, data)
|
|
57
|
+
config = write_config_file(path)
|
|
37
58
|
assert_equal 'bob', config.github_username
|
|
38
59
|
assert_equal key, config.key
|
|
39
60
|
assert_equal '/tmp', config.project_dir
|
|
40
61
|
end
|
|
41
62
|
|
|
42
63
|
def test_delete_config_file
|
|
43
|
-
|
|
44
|
-
'github_username' => 'bob',
|
|
45
|
-
'key' => key,
|
|
46
|
-
'project_dir' => '/tmp'
|
|
47
|
-
}
|
|
48
|
-
config = Exercism::Config.write(path, data)
|
|
64
|
+
config = write_config_file(path)
|
|
49
65
|
filename = config.file
|
|
50
66
|
config.delete
|
|
51
67
|
assert !File.exists?(filename)
|
|
52
68
|
end
|
|
53
69
|
|
|
54
70
|
def test_write_directory_if_missing
|
|
55
|
-
|
|
56
|
-
data
|
|
57
|
-
|
|
58
|
-
'key' => key,
|
|
59
|
-
'project_dir' => project_dir
|
|
60
|
-
}
|
|
61
|
-
Exercism::Config.write(path, data)
|
|
62
|
-
assert File.exist? project_dir
|
|
71
|
+
data = {'project_dir' => './test/fixtures/some/project/dir'}
|
|
72
|
+
write_config_file(path, data)
|
|
73
|
+
assert File.exist?(data['project_dir'])
|
|
63
74
|
end
|
|
64
75
|
|
|
65
76
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require './test/test_helper'
|
|
2
|
+
require 'exercism/submission'
|
|
3
|
+
|
|
4
|
+
class SubmissionTest < Minitest::Test
|
|
5
|
+
def test_knows_ruby_code
|
|
6
|
+
refute Exercism::Submission.test?('queens.rb')
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def test_identifies_ruby_tests
|
|
10
|
+
assert Exercism::Submission.test?('queens_test.rb')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test_knows_elixir_code
|
|
14
|
+
refute Exercism::Submission.test?('queens.exs')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_identifies_elixir_tests
|
|
18
|
+
assert Exercism::Submission.test?('queens_test.exs')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_knows_javascript_code
|
|
22
|
+
refute Exercism::Submission.test?('queens.js')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_identifies_javascript_tests
|
|
26
|
+
assert Exercism::Submission.test?('queens.spec.js')
|
|
27
|
+
end
|
|
28
|
+
end
|
data/test/exercism_test.rb
CHANGED
|
@@ -17,19 +17,11 @@ class ExercismTest < Minitest::Test
|
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def test_login_gives_you_a_user
|
|
21
|
-
Exercism.stub(:home, './test/fixtures') do
|
|
22
|
-
key = '97e9975'
|
|
23
|
-
user = Exercism.login('bob', key, '/tmp')
|
|
24
|
-
assert_equal 'bob', user.github_username
|
|
25
|
-
assert_equal key, user.key
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
20
|
def test_login_writes_the_config_file
|
|
30
|
-
|
|
21
|
+
home = './test/fixtures'
|
|
22
|
+
Exercism.stub(:home, home) do
|
|
31
23
|
key = '97e9975'
|
|
32
|
-
Exercism.login('bob', key, '/tmp')
|
|
24
|
+
Exercism.login('bob', key, '/tmp', home)
|
|
33
25
|
user = Exercism.user
|
|
34
26
|
assert_equal 'bob', user.github_username
|
|
35
27
|
assert_equal key, user.key
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: exercism
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.19
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,8 +9,24 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2013-07-
|
|
12
|
+
date: 2013-07-28 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: json
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ! '>='
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '0'
|
|
14
30
|
- !ruby/object:Gem::Dependency
|
|
15
31
|
name: faraday
|
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -176,11 +192,14 @@ files:
|
|
|
176
192
|
- lib/exercism/api.rb
|
|
177
193
|
- lib/exercism/assignment.rb
|
|
178
194
|
- lib/exercism/config.rb
|
|
195
|
+
- lib/exercism/env.rb
|
|
196
|
+
- lib/exercism/submission.rb
|
|
179
197
|
- lib/exercism/user.rb
|
|
180
198
|
- lib/exercism/version.rb
|
|
181
199
|
- test/exercism/api_test.rb
|
|
182
200
|
- test/exercism/assignment_test.rb
|
|
183
201
|
- test/exercism/config_test.rb
|
|
202
|
+
- test/exercism/submission_test.rb
|
|
184
203
|
- test/exercism_test.rb
|
|
185
204
|
- test/fixtures/approvals/alice_gets_bob_readme.approved.txt
|
|
186
205
|
- test/fixtures/approvals/alice_gets_bob_tests.approved.txt
|
|
@@ -221,6 +240,7 @@ test_files:
|
|
|
221
240
|
- test/exercism/api_test.rb
|
|
222
241
|
- test/exercism/assignment_test.rb
|
|
223
242
|
- test/exercism/config_test.rb
|
|
243
|
+
- test/exercism/submission_test.rb
|
|
224
244
|
- test/exercism_test.rb
|
|
225
245
|
- test/fixtures/approvals/alice_gets_bob_readme.approved.txt
|
|
226
246
|
- test/fixtures/approvals/alice_gets_bob_tests.approved.txt
|