bearcat 1.3.28 → 1.3.30
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 +4 -4
- data/bearcat.gemspec +3 -0
- data/lib/bearcat.rb +52 -0
- data/lib/bearcat/api_array.rb +6 -6
- data/lib/bearcat/client.rb +59 -3
- data/lib/bearcat/client/folders.rb +4 -0
- data/lib/bearcat/version.rb +1 -1
- data/spec/bearcat/client/folders_spec.rb +6 -0
- data/spec/fixtures/course_folder.json +21 -0
- metadata +46 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c8d7f5a1481dd58f3e09d2f0be117afb259ab7a
|
4
|
+
data.tar.gz: f1ee6a16c5616fe354a5f0ec7654166531d64663
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c5567c4f30375c5ab1db0a9f1f36d48e81beffcf28caccfb267344ee2ccd0376fe4643dc0341cf7b9d46f1e8ef005b92c88961b614139321194e102d68d5eef
|
7
|
+
data.tar.gz: 02abd72f687e7ac98b4b3fd1c6e8544fdbd16a0aec704cfa0816e185c3902bc5b8e733153bbc95971d4f64d800c178926ff88e5631cae52df578c4a80045de02
|
data/bearcat.gemspec
CHANGED
@@ -24,5 +24,8 @@ Gem::Specification.new do |gem|
|
|
24
24
|
gem.add_development_dependency "webmock"
|
25
25
|
gem.add_development_dependency 'pry'
|
26
26
|
|
27
|
+
gem.add_dependency "activesupport"
|
27
28
|
gem.add_dependency "footrest", ">= 0.2.2"
|
29
|
+
gem.add_dependency "logging", ">= 2.2.2"
|
30
|
+
gem.add_dependency "paul_walker", "~> 0.1.1"
|
28
31
|
end
|
data/lib/bearcat.rb
CHANGED
@@ -1,2 +1,54 @@
|
|
1
1
|
require 'bearcat/version'
|
2
2
|
require 'bearcat/client'
|
3
|
+
|
4
|
+
module Bearcat
|
5
|
+
class << self
|
6
|
+
require 'logging'
|
7
|
+
attr_writer :enforce_rate_limits, :rate_limit_min, :rate_limits, :max_sleep_seconds,
|
8
|
+
:min_sleep_seconds, :logger, :master_rate_limit, :master_mutex,
|
9
|
+
:rate_limit_threshold
|
10
|
+
|
11
|
+
def configure
|
12
|
+
yield self if block_given?
|
13
|
+
end
|
14
|
+
|
15
|
+
def rate_limit_min
|
16
|
+
@rate_limit_min ||= 175
|
17
|
+
end
|
18
|
+
|
19
|
+
def enforce_rate_limits
|
20
|
+
@enforce_rate_limits ||= false
|
21
|
+
end
|
22
|
+
|
23
|
+
def rate_limits
|
24
|
+
@rate_limits ||= {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def max_sleep_seconds
|
28
|
+
@max_sleep_seconds ||= 60
|
29
|
+
end
|
30
|
+
|
31
|
+
def master_rate_limit
|
32
|
+
@master_rate_limit ||= false
|
33
|
+
end
|
34
|
+
|
35
|
+
def master_mutex
|
36
|
+
@master_mutex ||= Mutex.new
|
37
|
+
end
|
38
|
+
|
39
|
+
def rate_limit_threshold
|
40
|
+
@rate_limit_threshold ||= 125
|
41
|
+
end
|
42
|
+
|
43
|
+
def logger
|
44
|
+
return @logger if defined? @logger
|
45
|
+
@logger = Logging.logger(STDOUT)
|
46
|
+
@logger.level = :debug
|
47
|
+
@logger
|
48
|
+
end
|
49
|
+
|
50
|
+
def min_sleep_seconds
|
51
|
+
@min_sleep_seconds ||= 5
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/bearcat/api_array.rb
CHANGED
@@ -19,12 +19,12 @@ module Bearcat
|
|
19
19
|
@array_key = array_key
|
20
20
|
@page_count = 100
|
21
21
|
case response.status
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
when 200..206
|
23
|
+
@members = process_body(response)
|
24
|
+
@status = response.status
|
25
|
+
@headers = response.headers
|
26
|
+
@method = response.env[:method]
|
27
|
+
init_pages(@headers['Link'])
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
data/lib/bearcat/client.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
require 'active_support/core_ext/hash'
|
1
2
|
require 'footrest/client'
|
3
|
+
require 'paul_walker'
|
4
|
+
|
2
5
|
module Bearcat
|
3
6
|
class Client < Footrest::Client
|
4
7
|
require 'bearcat/api_array'
|
@@ -70,11 +73,64 @@ module Bearcat
|
|
70
73
|
include CustomGradebookColumns
|
71
74
|
include ExternalTools
|
72
75
|
|
73
|
-
|
74
76
|
# Override Footrest request for ApiArray support
|
75
77
|
def request(method, &block)
|
76
|
-
|
78
|
+
enforce_rate_limits
|
79
|
+
response = connection.send(method, &block)
|
80
|
+
apply_rate_limits(response.headers['x-rate-limit-remaining'])
|
81
|
+
ApiArray.process_response(response, self)
|
82
|
+
end
|
83
|
+
|
84
|
+
def enforce_rate_limits
|
85
|
+
return unless limit_remaining.present?
|
86
|
+
return unless limit_remaining < Bearcat.rate_limit_min
|
87
|
+
|
88
|
+
tts = ((Bearcat.rate_limit_min - limit_remaining) / 5).ceil
|
89
|
+
tts = Bearcat.min_sleep_seconds if tts < Bearcat.min_sleep_seconds
|
90
|
+
tts = Bearcat.max_sleep_seconds if tts > Bearcat.max_sleep_seconds
|
91
|
+
|
92
|
+
|
93
|
+
message = "Canvas API rate limit minimum #{Bearcat.rate_limit_min} reached. "\
|
94
|
+
"Sleeping for #{tts} second(s) to catch up ~zzZZ~. "\
|
95
|
+
"Limit Remaining: #{limit_remaining}"
|
96
|
+
Bearcat.logger.debug(message)
|
97
|
+
|
98
|
+
sleep(tts)
|
77
99
|
end
|
78
|
-
end
|
79
100
|
|
101
|
+
def apply_rate_limits(limit)
|
102
|
+
return if limit.nil?
|
103
|
+
self.limit_remaining = limit.to_i
|
104
|
+
end
|
105
|
+
|
106
|
+
def using_master_rate_limit?
|
107
|
+
config[:master_rate_limit].present? || Bearcat.master_rate_limit.present?
|
108
|
+
end
|
109
|
+
|
110
|
+
def limit_remaining
|
111
|
+
if using_master_rate_limit?
|
112
|
+
Bearcat.master_mutex.synchronize do
|
113
|
+
limit = PaulWalker::RateLimit.get(config[:token], config[:token])
|
114
|
+
if limit.nil?
|
115
|
+
PaulWalker::RateLimit.add(config[:token], config[:token], 0, Bearcat::rate_limit_min)
|
116
|
+
limit = { current: 0 }.with_indifferent_access
|
117
|
+
end
|
118
|
+
Bearcat.logger.debug limit['current'].to_s
|
119
|
+
limit['current']
|
120
|
+
end
|
121
|
+
else
|
122
|
+
Bearcat.rate_limits[config[:token]]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def limit_remaining=(value)
|
127
|
+
if using_master_rate_limit?
|
128
|
+
Bearcat.master_mutex.synchronize do
|
129
|
+
PaulWalker::RateLimit.add(config[:token], config[:token], value, Bearcat::rate_limit_min)
|
130
|
+
end
|
131
|
+
else
|
132
|
+
Bearcat.rate_limits[config[:token]] = value
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
80
136
|
end
|
data/lib/bearcat/version.rb
CHANGED
@@ -9,4 +9,10 @@ describe Bearcat::Client::Folders do
|
|
9
9
|
expect(folders.map { |f| f['id'] }).to eql [1, 593]
|
10
10
|
expect(folders.map { |f| f['full_name'] }).to eql ['course files', 'course files/folder1']
|
11
11
|
end
|
12
|
+
|
13
|
+
it 'creates a new folder in a course' do
|
14
|
+
resp = stub_post(client, '/api/v1/courses/7/folders').to_return(json_response('course_folder.json'))
|
15
|
+
folder = client.create_course_folder(7, {name: 'new folder'})
|
16
|
+
expect(folder['name']).to eql('new folder')
|
17
|
+
end
|
12
18
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"context_id": 1,
|
3
|
+
"context_type": "Course",
|
4
|
+
"created_at": "2015-04-28T19:14:58Z",
|
5
|
+
"full_name": "new folder",
|
6
|
+
"id": 3,
|
7
|
+
"lock_at": null,
|
8
|
+
"name": "new folder",
|
9
|
+
"parent_folder_id": null,
|
10
|
+
"position": null,
|
11
|
+
"unlock_at": null,
|
12
|
+
"updated_at": "2015-04-28T19:14:58Z",
|
13
|
+
"locked": false,
|
14
|
+
"folders_url": "http://localhost:3000/api/v1/folders/1/folders",
|
15
|
+
"files_url": "http://localhost:3000/api/v1/folders/1/files",
|
16
|
+
"files_count": 2,
|
17
|
+
"folders_count": 1,
|
18
|
+
"hidden": null,
|
19
|
+
"locked_for_user": false,
|
20
|
+
"hidden_for_user": false
|
21
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bearcat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.30
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Mills, Jake Sorce
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-02-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activesupport
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: footrest
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +108,34 @@ dependencies:
|
|
94
108
|
- - ">="
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: 0.2.2
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: logging
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 2.2.2
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 2.2.2
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: paul_walker
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.1.1
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.1.1
|
97
139
|
description: Ruby interface for interacting with the canvas API
|
98
140
|
email:
|
99
141
|
- nathanm@instructure.com, jake@instructure.com
|
@@ -219,6 +261,7 @@ files:
|
|
219
261
|
- spec/fixtures/course_copy.json
|
220
262
|
- spec/fixtures/course_enrollments.json
|
221
263
|
- spec/fixtures/course_files.json
|
264
|
+
- spec/fixtures/course_folder.json
|
222
265
|
- spec/fixtures/course_folders.json
|
223
266
|
- spec/fixtures/course_grading_standards.json
|
224
267
|
- spec/fixtures/course_groups.json
|
@@ -380,6 +423,7 @@ test_files:
|
|
380
423
|
- spec/fixtures/course_files.json
|
381
424
|
- spec/fixtures/assignment_section_override.json
|
382
425
|
- spec/fixtures/delete_course.json
|
426
|
+
- spec/fixtures/course_folder.json
|
383
427
|
- spec/fixtures/ok.json
|
384
428
|
- spec/fixtures/account_sub_accounts.json
|
385
429
|
- spec/fixtures/course_sections.json
|