sakai-info 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,13 @@
1
1
  # sakai-info Change History #
2
2
 
3
+ ### 0.5.2 ###
4
+
5
+ *Released 2012-10-11*
6
+
7
+ * Added JSON output option for lookups
8
+ * Proof-of-concept sin shell
9
+ * Alias support
10
+
3
11
  ### 0.5.1 ###
4
12
 
5
13
  *Released 2012-10-07*
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # sakai-info #
2
2
 
3
- last updated: 2012-10-07
3
+ last updated: 2012-10-11
4
4
  author: David Adams (daveadams@gmail.com)
5
5
  github url: https://github.com/daveadams/sakai-info
6
6
 
@@ -24,7 +24,7 @@ Use `rake` to test and build the gem:
24
24
  $ rake gem:build
25
25
 
26
26
  The resulting gem will be saved to the working directory as
27
- `sakai-info-0.5.1.gem`.
27
+ `sakai-info-0.5.2.gem`.
28
28
 
29
29
  Cleanup built gems using:
30
30
 
data/ROADMAP.md CHANGED
@@ -1,43 +1,37 @@
1
1
  # sakai-info Roadmap #
2
2
 
3
- *Last updated 2012-10-07*
3
+ *Last updated 2012-10-11*
4
4
 
5
- ### 0.5.2 ###
5
+ ### 0.5.3 ###
6
6
 
7
- * JSON output support
8
7
  * Ability to specify alternate config file at the command line
9
8
  * Better date formatting and proper time zone understanding
10
9
  * More query functionality
11
- * Proof-of-concept sin shell
12
- * Chat channel/message support
13
- * Alias support
10
+ * OSP presentation/metaobj support
14
11
  * Add simple tests against user/site fixture data
12
+ * More query and shell functionality
15
13
 
16
- ### 0.5.3 ###
14
+ ### 0.5.4 ###
17
15
 
18
16
  * RDS schema creation and data loading for MySQL and Oracle testing
19
17
  * More query and shell functionality
20
18
  * Test fixture generation for quizzes
19
+ * Chat channel/message support
20
+ * More OSP support
21
21
 
22
- ### 0.5.4 ###
22
+ ### 0.5.5 ###
23
23
 
24
24
  * Barebones web interface - HTML, JSON, and YAML
25
25
  * More query and shell functionality
26
+ * Complete OSP support
26
27
 
27
- ### 0.5.5 ###
28
+ ### 0.6.x ###
28
29
 
29
30
  * Global cache instead of per-class
30
31
  * More query, web, and shell functionality
31
-
32
- ### 0.6.x ###
33
-
34
32
  * Test fixtures and basic unit tests for all represented objects
35
33
  * RDoc coverage for every class
36
- * More focus on other library usage besides ad hoc CLI/web queries
37
-
38
- ### 0.7.x ###
39
-
40
- * OSP support
34
+ * Grow support for other library usage besides ad hoc queries
41
35
 
42
36
  ------
43
37
 
data/bin/sin CHANGED
@@ -5,7 +5,7 @@
5
5
  # sakai-info library
6
6
  #
7
7
  # Created 2012-02-15 daveadams@gmail.com
8
- # Last updated 2012-05-23 daveadams@gmail.com
8
+ # Last updated 2012-10-09 daveadams@gmail.com
9
9
  #
10
10
  # https://github.com/daveadams/sakai-info
11
11
  #
@@ -107,6 +107,9 @@ when "test" then
107
107
  when "query" then
108
108
  mode = args.shift
109
109
 
110
+ when "shell" then
111
+ mode = args.shift
112
+
110
113
  else
111
114
  # test to see if it's an accepted lookup mode
112
115
  if CLI::LookupModes.keys.include? args[0]
@@ -151,5 +154,8 @@ when "lookup"
151
154
  when "special"
152
155
  CLI::Special.process(args, flags)
153
156
 
157
+ when "shell"
158
+ CLI::Shell.process(args, flags)
159
+
154
160
  end
155
161
 
@@ -2,7 +2,7 @@
2
2
  # Base library file
3
3
  #
4
4
  # Created 2012-02-15 daveadams@gmail.com
5
- # Last updated 2012-05-20 daveadams@gmail.com
5
+ # Last updated 2012-10-11 daveadams@gmail.com
6
6
  #
7
7
  # https://github.com/daveadams/sakai-info
8
8
  #
@@ -46,4 +46,5 @@ require 'sakai-info/question_pool'
46
46
  require 'sakai-info/generic_message'
47
47
  require 'sakai-info/forum'
48
48
  require 'sakai-info/private_message'
49
+ require 'sakai-info/alias'
49
50
 
@@ -0,0 +1,136 @@
1
+ # sakai-info/alias.rb
2
+ # SakaiInfo::Alias library
3
+ #
4
+ # Created 2012-10-11 daveadams@gmail.com
5
+ # Last updated 2012-10-11 daveadams@gmail.com
6
+ #
7
+ # https://github.com/daveadams/sakai-info
8
+ #
9
+ # This software is public domain.
10
+ #
11
+
12
+ module SakaiInfo
13
+ class Alias < SakaiObject
14
+ attr_reader :target, :dbrow
15
+
16
+ include ModProps
17
+ created_by_key :createdby
18
+ created_at_key :createdon
19
+ modified_by_key :modifiedby
20
+ modified_at_key :modifiedon
21
+
22
+ def self.clear_cache
23
+ @@cache = {}
24
+ end
25
+ clear_cache
26
+
27
+ def initialize(dbrow)
28
+ @dbrow = dbrow
29
+
30
+ @id = dbrow[:alias_id]
31
+ @target = dbrow[:target]
32
+ end
33
+
34
+ # target types
35
+ # /mailarchive/channel/<site-id>/main
36
+ # /site/<site-id>
37
+ # /announcement/announcement/<site-id> -> rss feed
38
+ def site_id
39
+ if @target.nil?
40
+ nil
41
+ else
42
+ if @target =~ /^\/site\/(.+)$/
43
+ $1
44
+ elsif @target =~ /^\/mailarchive\/channel\/(.+)\/main$/
45
+ $1
46
+ elsif @target =~ /^\/announcement\/announcement\/(.+)$/
47
+ $1
48
+ else
49
+ nil
50
+ end
51
+ end
52
+ end
53
+
54
+ def site
55
+ if not self.site_id.nil?
56
+ @site ||= Site.find(self.site_id)
57
+ end
58
+ end
59
+
60
+ def self.find(id)
61
+ if @@cache[id].nil?
62
+ row = DB.connect[:sakai_alias].filter(:alias_id => id).first
63
+ if row.nil?
64
+ raise ObjectNotFoundException.new(Alias, id)
65
+ end
66
+ @@cache[id] = Alias.new(row)
67
+ end
68
+ @@cache[id]
69
+ end
70
+
71
+ def self.query_by_site_id(site_id)
72
+ DB.connect[:sakai_alias].where("target like ?", "%#{site_id}%")
73
+ end
74
+
75
+ def self.find_by_site_id(site_id)
76
+ Alias.query_by_site_id(site_id).all.
77
+ collect { |row| @@cache[row[:alias_id]] = Alias.new(row) }
78
+ end
79
+
80
+ def self.count_by_site_id(site_id)
81
+ Alias.query_by_site_id(site_id).count
82
+ end
83
+
84
+ def properties
85
+ @properties ||= AliasProperty.find_by_alias_id(self.id)
86
+ end
87
+
88
+ # serialization
89
+ def default_serialization
90
+ result = {
91
+ "id" => self.id,
92
+ "target" => self.target,
93
+ "site" => nil,
94
+ "properties" => self.properties,
95
+ }
96
+ if not self.site.nil?
97
+ result["site"] = self.site.serialize(:summary)
98
+ else
99
+ result.delete("site")
100
+ end
101
+ result
102
+ end
103
+
104
+ def summary_serialization
105
+ {
106
+ "id" => self.id,
107
+ "target" => self.target,
108
+ }
109
+ end
110
+
111
+ def self.all_serializations
112
+ [:default, :mod]
113
+ end
114
+ end
115
+
116
+ class AliasProperty
117
+ def self.get(id, property_name)
118
+ row = DB.connect[:sakai_alias_property].
119
+ filter(:alias_id => id, :name => property_name).first
120
+ if row.nil?
121
+ nil
122
+ else
123
+ row[:value].read
124
+ end
125
+ end
126
+
127
+ def self.find_by_alias_id(id)
128
+ properties = {}
129
+ DB.connect[:sakai_alias_property].
130
+ where(:alias_id => id).all.each do |row|
131
+ properties[row[:name]] = row[:value].read
132
+ end
133
+ return properties
134
+ end
135
+ end
136
+ end
@@ -2,7 +2,7 @@
2
2
  # - sakai-info command line tool support
3
3
  #
4
4
  # Created 2012-02-19 daveadams@gmail.com
5
- # Last updated 2012-06-21 daveadams@gmail.com
5
+ # Last updated 2012-10-07 daveadams@gmail.com
6
6
  #
7
7
  # https://github.com/daveadams/sakai-info
8
8
  #
@@ -13,6 +13,7 @@ require 'sakai-info/cli/help'
13
13
  require 'sakai-info/cli/lookup'
14
14
  require 'sakai-info/cli/query'
15
15
  require 'sakai-info/cli/special'
16
+ require 'sakai-info/cli/shell'
16
17
 
17
18
  # it's faster to run single-threaded
18
19
  Sequel.single_threaded = true
@@ -2,7 +2,7 @@
2
2
  # - sin command line help
3
3
  #
4
4
  # Created 2012-02-19 daveadams@gmail.com
5
- # Last updated 2012-10-03 daveadams@gmail.com
5
+ # Last updated 2012-10-11 daveadams@gmail.com
6
6
  #
7
7
  # https://github.com/daveadams/sakai-info
8
8
  #
@@ -29,7 +29,7 @@ Sakai INfo: sin #{VERSION}
29
29
  quiz-attempt-item-attachment, question-pool, assignment,
30
30
  assignment-submission, forum, forum-thread, forum-post, content,
31
31
  announcement, announcement-channel, gradebook, gradebook-item,
32
- role, function, realm, private-message
32
+ role, function, realm, private-message, alias
33
33
 
34
34
  QUERY MODE
35
35
  Query particular fields from certain objects given certain conditions.
@@ -470,6 +470,16 @@ sin private-message
470
470
  Prints information about the private message ID specified. Additional options
471
471
  may be passed to include additional information:
472
472
 
473
+ --mod Print creation/modification info
474
+ EOF
475
+ "alias" => <<EOF,
476
+ sin alias
477
+
478
+ Usage: sin alias <id> [<options>]
479
+
480
+ Prints information about the alias ID specified. Additional options may be
481
+ passed to include additional information:
482
+
473
483
  --mod Print creation/modification info
474
484
  EOF
475
485
  "query" => <<EOF,
@@ -2,7 +2,7 @@
2
2
  # class for handling the default command line mode
3
3
  #
4
4
  # Created 2012-05-23 daveadams@gmail.com
5
- # Last updated 2012-06-21 daveadams@gmail.com
5
+ # Last updated 2012-10-11 daveadams@gmail.com
6
6
  #
7
7
  # https://github.com/daveadams/sakai-info
8
8
  #
@@ -16,14 +16,23 @@ module SakaiInfo
16
16
  object_type = args.shift
17
17
  id = args.shift
18
18
  fields = nil
19
+ output = :yaml
19
20
 
21
+ flags_to_delete = []
20
22
  flags.each do |flag|
21
23
  if flag =~ /^--fields=(.+)$/
22
24
  fields = $1.downcase.split(',')
23
- flags.delete(flag)
25
+ flags_to_delete << flag
26
+ elsif flag == "--json"
27
+ output = :json
28
+ flags_to_delete << flag
24
29
  end
25
30
  end
26
31
 
32
+ flags_to_delete.each do |flag|
33
+ flags.delete(flag)
34
+ end
35
+
27
36
  if flags.include? "--all"
28
37
  serials = CLI::LookupModes[object_type].all_serializations
29
38
  elsif flags.include? "--dbrow-only"
@@ -36,20 +45,28 @@ module SakaiInfo
36
45
  begin
37
46
  object = CLI::LookupModes[object_type].find(id)
38
47
  rescue ObjectNotFoundException => e
39
- STDERR.puts "ERROR: Could not find #{object_type} with an ID of '#{id}':"
40
- STDERR.puts " #{e}"
48
+ STDERR.puts "ERROR: #{e}"
41
49
  exit 1
42
50
  end
43
51
 
44
52
  if fields.nil? or fields.empty?
45
- puts object.to_yaml(serials)
53
+ if output == :json
54
+ puts object.to_json(serials)
55
+ else
56
+ puts object.to_yaml(serials)
57
+ end
58
+
46
59
  else
47
60
  object_hash = object.serialize(serials).delete_if{|k,v| not fields.include? k.to_s}
48
61
  if object_hash.empty?
49
62
  STDERR.puts "ERROR: no requested fields were found"
50
63
  exit 1
51
64
  end
52
- puts object_hash.to_yaml
65
+ if output == :json
66
+ puts object_hash.to_json
67
+ else
68
+ puts object_hash.to_yaml
69
+ end
53
70
  end
54
71
  end
55
72
  end
@@ -120,6 +137,7 @@ module SakaiInfo
120
137
  "realm" => AuthzRealm,
121
138
  "private-message" => PrivateMessage,
122
139
  "pm" => PrivateMessage,
140
+ "alias" => Alias,
123
141
  }
124
142
  end
125
143
  end
@@ -2,7 +2,7 @@
2
2
  # class for handling "query" command line mode
3
3
  #
4
4
  # Created 2012-05-23 daveadams@gmail.com
5
- # Last updated 2012-10-06 daveadams@gmail.com
5
+ # Last updated 2012-10-09 daveadams@gmail.com
6
6
  #
7
7
  # https://github.com/daveadams/sakai-info
8
8
  #
@@ -87,6 +87,34 @@ module SakaiInfo
87
87
  puts user.to_csv(:eid, :name)
88
88
  end
89
89
 
90
+ elsif object_type == "quiz-attempt"
91
+ eid = args.shift
92
+ quiz_id = args.shift
93
+ user = nil
94
+ quiz = nil
95
+
96
+ begin
97
+ user = User.find(eid)
98
+ quiz = PublishedQuiz.find(quiz_id)
99
+ rescue ObjectNotFoundException => e
100
+ STDERR.puts "ERROR: #{e}"
101
+ exit 1
102
+ end
103
+
104
+ if user.nil? or quiz.nil?
105
+ STDERR.puts "ERROR: could not find user or quiz object"
106
+ exit 1
107
+ end
108
+
109
+ attempts = quiz.user_attempts(user.id)
110
+ if attempts.nil? or attempts.empty?
111
+ STDERR.puts "ERROR: no attempts found"
112
+ end
113
+
114
+ attempts.each do |att|
115
+ puts att.to_yaml
116
+ end
117
+
90
118
  else
91
119
  STDERR.puts "ERROR: Unrecognized object type"
92
120
  exit 1
@@ -0,0 +1,99 @@
1
+ # shell.rb
2
+ # sin shell
3
+ #
4
+ # Created 2012-10-07 daveadams@gmail.com
5
+ # Last updated 2012-10-07 daveadams@gmail.com
6
+ #
7
+ # https://github.com/daveadams/sakai-info
8
+ #
9
+ # This software is public domain.
10
+ #
11
+
12
+ module SakaiInfo
13
+ module CLI
14
+ class Shell
15
+ def self.process(args, flags)
16
+ Shell.new.run
17
+ end
18
+
19
+ def initialize
20
+ @context = nil
21
+ @context_history = []
22
+ @running = true
23
+ end
24
+
25
+ def context_prompt
26
+ if @context.nil?
27
+ "[-]"
28
+ else
29
+ # TODO: implement ShellContext object
30
+ #@context.brief_name
31
+ "[!]"
32
+ end
33
+ end
34
+
35
+ def prompt
36
+ print "sin#{context_prompt}> ";STDOUT.flush
37
+ gets
38
+ end
39
+
40
+ def run
41
+ while @running do
42
+ input = prompt
43
+
44
+ # a ctrl-D sends nil
45
+ if input.nil?
46
+ puts "exit"
47
+ break
48
+ end
49
+
50
+ argv = input.chomp.split(/ +/)
51
+ command = argv.shift.downcase
52
+ method_name = ("_shell_command_#{command}").to_sym
53
+
54
+ if Shell.method_defined? method_name
55
+ self.method(method_name).call(argv)
56
+ else
57
+ STDERR.puts "ERROR: unknown command '#{command}'"
58
+ end
59
+ end
60
+
61
+ # TODO: any additional cleanup here
62
+ end
63
+
64
+ def _shell_command_quit(argv)
65
+ @running = false
66
+ end
67
+
68
+ alias_method :_shell_command_exit, :_shell_command_quit
69
+
70
+ def _shell_command_count(argv)
71
+ case argv[0].downcase
72
+ when /^users?$/
73
+ puts User.count
74
+ when /^sites?$/
75
+ puts Site.count
76
+ else
77
+ STDERR.puts("ERROR: unrecognized object type")
78
+ end
79
+ end
80
+
81
+ def _shell_command_user(argv)
82
+ user = nil
83
+ begin
84
+ user = User.find(argv[0])
85
+ rescue ObjectNotFoundException => e
86
+ STDERR.puts "ERROR: could not find user '#{argv[0]}'"
87
+ STDERR.puts " #{e}"
88
+ return
89
+ end
90
+
91
+ return if user.nil?
92
+
93
+ puts user.to_yaml(:shell)
94
+ end
95
+
96
+ end
97
+ end
98
+ end
99
+
@@ -2,7 +2,7 @@
2
2
  # SakaiInfo::Quiz library
3
3
  #
4
4
  # Created 2012-02-17 daveadams@gmail.com
5
- # Last updated 2012-09-29 daveadams@gmail.com
5
+ # Last updated 2012-10-11 daveadams@gmail.com
6
6
  #
7
7
  # https://github.com/daveadams/sakai-info
8
8
  #
@@ -304,6 +304,10 @@ module SakaiInfo
304
304
  PublishedQuiz.query_by_site_id(site_id).select(:id).all.collect { |row| row[:id] }
305
305
  end
306
306
 
307
+ def user_attempts(user_id)
308
+ QuizAttempt.find_by_user_id_and_quiz_id(user_id, self.id)
309
+ end
310
+
307
311
  def quiz_type
308
312
  "published"
309
313
  end
@@ -784,6 +788,15 @@ module SakaiInfo
784
788
  all.collect { |row| QuizAttempt.new(row) }
785
789
  end
786
790
 
791
+ def self.query_by_user_id_and_quiz_id(user_id, quiz_id)
792
+ DB.connect[:sam_assessmentgrading_t].where(:publishedassessmentid => quiz_id, :agentid => user_id)
793
+ end
794
+
795
+ def self.find_by_user_id_and_quiz_id(user_id, quiz_id)
796
+ QuizAttempt.query_by_user_id_and_quiz_id(user_id, quiz_id).
797
+ all.collect { |row| QuizAttempt.new(row) }
798
+ end
799
+
787
800
  def items
788
801
  @items ||= QuizAttemptItem.find_by_attempt_id(self.id)
789
802
  end
@@ -1129,7 +1142,11 @@ module SakaiInfo
1129
1142
  end
1130
1143
 
1131
1144
  def timed?
1132
- @dbrow[:timelimit] > 0
1145
+ if time_limit.nil?
1146
+ false
1147
+ else
1148
+ time_limit > 0
1149
+ end
1133
1150
  end
1134
1151
 
1135
1152
  def automatic_submission?
@@ -2,7 +2,7 @@
2
2
  # SakaiInfo::SakaiObject
3
3
  #
4
4
  # Created 2012-02-15 daveadams@gmail.com
5
- # Last updated 2012-10-06 daveadams@gmail.com
5
+ # Last updated 2012-10-08 daveadams@gmail.com
6
6
  #
7
7
  # https://github.com/daveadams/sakai-info
8
8
  #
@@ -62,6 +62,14 @@ module SakaiInfo
62
62
  object_type_serialization
63
63
  end
64
64
 
65
+ def summary_serialization
66
+ default_serialization
67
+ end
68
+
69
+ def shell_serialization
70
+ summary_serialization
71
+ end
72
+
65
73
  def to_yaml(*q)
66
74
  serialize(q).to_yaml
67
75
  end
@@ -1,3 +1,3 @@
1
1
  module SakaiInfo
2
- VERSION = "0.5.1"
2
+ VERSION = "0.5.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sakai-info
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-07 00:00:00.000000000 Z
12
+ date: 2012-10-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sequel
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: marky_markov
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
46
62
  description: A command line tool and a suite of libraries for representing the objects
47
63
  and relationships defined by a Sakai CLE database.
48
64
  email: daveadams@gmail.com
@@ -52,6 +68,7 @@ extensions: []
52
68
  extra_rdoc_files: []
53
69
  files:
54
70
  - lib/sakai-info.rb
71
+ - lib/sakai-info/alias.rb
55
72
  - lib/sakai-info/util.rb
56
73
  - lib/sakai-info/group.rb
57
74
  - lib/sakai-info/private_message.rb
@@ -59,6 +76,7 @@ files:
59
76
  - lib/sakai-info/cli/help.rb
60
77
  - lib/sakai-info/cli/query.rb
61
78
  - lib/sakai-info/cli/special.rb
79
+ - lib/sakai-info/cli/shell.rb
62
80
  - lib/sakai-info/cli/lookup.rb
63
81
  - lib/sakai-info/site.rb
64
82
  - lib/sakai-info/cache.rb