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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f647eb5f21166dc1aa4383ff33184be11d127b60
4
- data.tar.gz: ce49a99cbdb58e448c2738696a8aea07a2cc441d
3
+ metadata.gz: 5c8d7f5a1481dd58f3e09d2f0be117afb259ab7a
4
+ data.tar.gz: f1ee6a16c5616fe354a5f0ec7654166531d64663
5
5
  SHA512:
6
- metadata.gz: 78df1f29163a3d1aa42a1dfdb2801ba5c623000d3e2c3ed644ec2c41fca00ebe3fcc4048c62217a584600fc6952ba5d70adfc51512a3bba836e80a5aa485d535
7
- data.tar.gz: a128860bd32263d21ddceee32fced977f3b86016609022dc3b3757d8a2a3ef6592398ded9d6c4215ded32d2fb3be394c76100a531738d3ec7bc9b92fe02351c4
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
@@ -19,12 +19,12 @@ module Bearcat
19
19
  @array_key = array_key
20
20
  @page_count = 100
21
21
  case response.status
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'])
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
 
@@ -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
- ApiArray::process_response(connection.send(method, &block), self)
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
@@ -5,6 +5,10 @@ module Bearcat
5
5
  def list_course_folders(course, params = {})
6
6
  get("/api/v1/courses/#{course}/folders", params)
7
7
  end
8
+
9
+ def create_course_folder(course, params = {})
10
+ post("/api/v1/courses/#{course}/folders", params)
11
+ end
8
12
  end
9
13
  end
10
14
  end
@@ -1,3 +1,3 @@
1
1
  module Bearcat
2
- VERSION = '1.3.28' unless defined?(Bearcat::VERSION)
2
+ VERSION = '1.3.30' unless defined?(Bearcat::VERSION)
3
3
  end
@@ -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.28
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: 2018-11-29 00:00:00.000000000 Z
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