sakai-info 0.5.1 → 0.5.2

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.
@@ -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