github_api 0.4.11 → 0.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/README.md +76 -72
  2. data/features/cassettes/gists/starred.yml +48 -0
  3. data/features/cassettes/pagination/repos/commits/list.yml +193 -0
  4. data/features/cassettes/pagination/repos/commits/next.yml +183 -0
  5. data/features/cassettes/pagination/repos/diff/next.yml +45 -0
  6. data/features/cassettes/pagination/repos/list.yml +176 -0
  7. data/features/cassettes/pagination/repos/list/next.yml +222 -0
  8. data/features/cassettes/pagination/repos/per_page/each_page.yml +45 -0
  9. data/features/cassettes/repos/list.yml +92 -0
  10. data/features/error_codes.feature +1 -1
  11. data/features/gists.feature +12 -3
  12. data/features/gists/comments.feature +3 -3
  13. data/features/github_api.feature +13 -2
  14. data/features/pagination.feature +40 -39
  15. data/features/repos.feature +2 -2
  16. data/features/step_definitions/common_steps.rb +12 -0
  17. data/features/step_definitions/github_api_steps.rb +12 -1
  18. data/lib/github_api.rb +1 -1
  19. data/lib/github_api/api.rb +4 -2
  20. data/lib/github_api/api_factory.rb +11 -5
  21. data/lib/github_api/authorizations.rb +23 -32
  22. data/lib/github_api/client.rb +1 -0
  23. data/lib/github_api/events.rb +38 -38
  24. data/lib/github_api/filter.rb +1 -1
  25. data/lib/github_api/gists.rb +47 -42
  26. data/lib/github_api/gists/comments.rb +77 -84
  27. data/lib/github_api/git_data.rb +25 -6
  28. data/lib/github_api/git_data/blobs.rb +48 -45
  29. data/lib/github_api/git_data/commits.rb +76 -73
  30. data/lib/github_api/git_data/references.rb +137 -118
  31. data/lib/github_api/git_data/tags.rb +74 -70
  32. data/lib/github_api/git_data/trees.rb +88 -85
  33. data/lib/github_api/issues.rb +43 -31
  34. data/lib/github_api/issues/comments.rb +116 -119
  35. data/lib/github_api/issues/events.rb +20 -19
  36. data/lib/github_api/issues/labels.rb +200 -197
  37. data/lib/github_api/issues/milestones.rb +137 -134
  38. data/lib/github_api/orgs.rb +27 -23
  39. data/lib/github_api/orgs/members.rb +105 -108
  40. data/lib/github_api/orgs/teams.rb +236 -237
  41. data/lib/github_api/paged_request.rb +1 -1
  42. data/lib/github_api/pull_requests.rb +40 -42
  43. data/lib/github_api/pull_requests/comments.rb +140 -143
  44. data/lib/github_api/repos.rb +101 -67
  45. data/lib/github_api/repos/collaborators.rb +64 -68
  46. data/lib/github_api/repos/commits.rb +50 -39
  47. data/lib/github_api/repos/downloads.rb +107 -110
  48. data/lib/github_api/repos/forks.rb +38 -39
  49. data/lib/github_api/repos/hooks.rb +161 -167
  50. data/lib/github_api/repos/keys.rb +86 -86
  51. data/lib/github_api/repos/pub_sub_hubbub.rb +99 -87
  52. data/lib/github_api/repos/watching.rb +80 -82
  53. data/lib/github_api/request.rb +5 -9
  54. data/lib/github_api/users.rb +26 -16
  55. data/lib/github_api/users/emails.rb +47 -47
  56. data/lib/github_api/users/followers.rb +85 -86
  57. data/lib/github_api/users/keys.rb +73 -75
  58. data/lib/github_api/validations.rb +25 -0
  59. data/lib/github_api/validations/format.rb +23 -0
  60. data/lib/github_api/validations/presence.rb +25 -0
  61. data/lib/github_api/validations/required.rb +21 -0
  62. data/lib/github_api/validations/token.rb +41 -0
  63. data/lib/github_api/version.rb +3 -3
  64. data/spec/fixtures/repos/commit_comparison.json +112 -0
  65. data/spec/github/api_factory_spec.rb +17 -1
  66. data/spec/github/authorizations_spec.rb +36 -34
  67. data/spec/github/gists/comments_spec.rb +39 -45
  68. data/spec/github/gists_spec.rb +50 -53
  69. data/spec/github/git_data/blobs_spec.rb +27 -20
  70. data/spec/github/git_data/commits_spec.rb +20 -19
  71. data/spec/github/git_data/references_spec.rb +83 -46
  72. data/spec/github/git_data/tags_spec.rb +16 -15
  73. data/spec/github/git_data/trees_spec.rb +20 -19
  74. data/spec/github/git_data_spec.rb +10 -1
  75. data/spec/github/issues/comments_spec.rb +78 -68
  76. data/spec/github/issues/events_spec.rb +42 -34
  77. data/spec/github/issues/labels_spec.rb +89 -101
  78. data/spec/github/issues/milestones_spec.rb +76 -54
  79. data/spec/github/issues_spec.rb +53 -57
  80. data/spec/github/orgs/members_spec.rb +64 -49
  81. data/spec/github/orgs/teams_spec.rb +112 -101
  82. data/spec/github/orgs_spec.rb +41 -31
  83. data/spec/github/paged_request_spec.rb +6 -5
  84. data/spec/github/pull_requests/comments_spec.rb +39 -44
  85. data/spec/github/pull_requests_spec.rb +32 -48
  86. data/spec/github/repos/collaborators_spec.rb +40 -29
  87. data/spec/github/repos/commits_spec.rb +108 -64
  88. data/spec/github/repos/downloads_spec.rb +46 -45
  89. data/spec/github/repos/forks_spec.rb +23 -24
  90. data/spec/github/repos/hooks_spec.rb +69 -71
  91. data/spec/github/repos/keys_spec.rb +39 -34
  92. data/spec/github/repos/pub_sub_hubbub_spec.rb +4 -4
  93. data/spec/github/repos/watching_spec.rb +31 -33
  94. data/spec/github/repos_spec.rb +74 -83
  95. data/spec/github/request_spec.rb +31 -2
  96. data/spec/github/users/emails_spec.rb +19 -17
  97. data/spec/github/users/followers_spec.rb +30 -28
  98. data/spec/github/users/keys_spec.rb +37 -33
  99. data/spec/github/users_spec.rb +124 -125
  100. data/spec/github/validations/format_spec.rb +42 -0
  101. data/spec/github/validations/presence_spec.rb +18 -0
  102. data/spec/github/validations/required_spec.rb +28 -0
  103. data/spec/github/validations/token_spec.rb +19 -0
  104. data/spec/github/validations_spec.rb +23 -0
  105. metadata +33 -10
  106. data/features/cassettes/pagination/repos.yml +0 -177
  107. data/features/cassettes/pagination/repos/next.yml +0 -177
  108. data/lib/github_api/validation.rb +0 -53
  109. data/spec/github/validation_spec.rb +0 -62
data/README.md CHANGED
@@ -10,6 +10,19 @@ A Ruby wrapper for the GitHub REST API v3.
10
10
 
11
11
  Supports all the API methods(nearly 200). It's build in a modular way, that is, you can either instantiate the whole api wrapper Github.new or use parts of it e.i. Github::Repos.new if working solely with repositories is your main concern.
12
12
 
13
+ ## Important!!
14
+ Since version 0.5 the way the gem queries the GitHub api underwent important changes. It closely mirros the Github api hierarchy e.i. if you want to create a download resource, lookup the github api spec and issue the request as in `github.repos.downloads.create`
15
+
16
+ ```ruby
17
+ Old style: github.pull_requests.create_request
18
+ github.pull_requests.pull_requests
19
+ github.pull_requests.pull_request
20
+
21
+ New style: github.pull_requests.create
22
+ github.pull_requests.all
23
+ github.pull_requests.find
24
+ ```
25
+
13
26
  ## Installation
14
27
 
15
28
  Install the gem by issuing
@@ -18,7 +31,7 @@ Install the gem by issuing
18
31
  gem install github_api
19
32
  ```
20
33
 
21
- or put it in your Gemfile and run `bundle install`</tt>
34
+ or put it in your Gemfile and run `bundle install`
22
35
 
23
36
  ```ruby
24
37
  gem "github_api"
@@ -29,61 +42,47 @@ gem "github_api"
29
42
  Create a new client instance
30
43
 
31
44
  ```ruby
32
- @github = Github.new
45
+ github = Github.new
33
46
  ```
34
47
 
35
48
  At this stage you can also supply various configuration parameters, such as `:user`,`:repo`, `:org`, `:oauth_token`, `:login`, `:password` or `:basic_auth` which are used throughout the API
36
49
 
37
50
  ```ruby
38
- @github = Github.new :user => 'peter-murach', :repo => 'github-api'
39
- ```
40
-
41
- or
42
-
43
- ```ruby
44
- @github = Github.new do |opts|
45
- opts.user = 'peter-murach'
46
- opts.repo = 'github-api'
47
- end
51
+ github = Github.new oauth_token: 'token'
48
52
  ```
49
53
 
50
54
  You can authenticate either using OAuth authentication convenience methods(see section OAuth) or through basic authentication by passing your login and password credentials
51
55
 
52
56
  ```ruby
53
- @github = Github.new :login => 'peter-murach', :password => '...'
57
+ github = Github.new login:'peter-murach', password:'...'
54
58
  ```
55
59
 
56
60
  or use convenience method:
57
61
 
58
62
  ```ruby
59
- @github = Github.new :basic_auth => 'login:password'
63
+ github = Github.new basic_auth: 'login:password'
60
64
  ```
61
65
 
62
- You can interact with GitHub interface, for example repositories, by issueing following calls
66
+ You can interact with GitHub interface, for example repositories, by issueing following calls that correspond directly to the GitHub API hierarchy
63
67
 
64
68
  ```ruby
65
- @github.repos.commits
66
- @github.repos.branches
67
- @github.repos.contributors
69
+ github.repos.commits.all 'user-name', 'repo-name'
70
+ github.repos.hooks.create 'user-name', 'repo-name', name: "web", active: true
71
+ github.repos.keys.get 'user-name', 'repo-name'
68
72
  ```
69
73
 
70
- The code base is modular and allows for you to work specifically with a given part of GitHub API e.g. repositories
74
+ The code base is modular and allows for you to work specifically with a given part of GitHub API e.g. blobs
71
75
 
72
76
  ```ruby
73
- @repos = Github::Repos.new
74
- @repos.branches 'peter-murach', 'github'
75
-
76
- or
77
-
78
- @repos = Github::Repos.new :user => 'peter-murach', :repo => 'github'
79
- @repos.branches
77
+ blobs = Github::GitData::Blobs.new
78
+ blobs.create 'peter-murach', 'github', content: 'Blob content'
80
79
  ```
81
80
 
82
81
  The response is of type [Hashie::Mash] and allows to traverse all the json response attributes like method calls e.i.
83
82
 
84
83
  ```ruby
85
- @repos = Github::Repos.new :user => 'peter-murach', :repo => 'github'
86
- @repos.branches do |branch|
84
+ repos = Github::Repos.new :user => 'peter-murach', :repo => 'github'
85
+ repos.branches do |branch|
87
86
  puts branch.name
88
87
  end
89
88
  ```
@@ -94,15 +93,10 @@ Main API methods are grouped into the following classes that can be instantiated
94
93
 
95
94
  ```ruby
96
95
  Github - full API access
97
- Github::Gists
98
- Github::GitData
99
- Github::Issues
100
- Github::Orgs
101
- Github::PullRequests
102
- Github::Repos
103
- Github::Users
104
- Github::Events
105
- Github::Authorizations
96
+
97
+ Github::Gists Github::GitData Github::Repos
98
+ Github::Orgs Github::Issues Github::Authorizations
99
+ Github::PullRequests Github::Users Github::Events
106
100
  ```
107
101
 
108
102
  Some parts of GitHub API v3 require you to be autheticated, for instance the following are examples of APIs only for the authenticated user
@@ -115,14 +109,13 @@ Github::Users::Keys
115
109
  All method calls form ruby like sentences and allow for intuitive api navigation, for instance
116
110
 
117
111
  ```ruby
118
- @github = Github.new :oauth_token => '...'
119
- @github.users.following 'wycats' # => returns users that 'wycats' is following
120
- @github.users.following 'wycats' # => returns true if following, otherwise false
112
+ github = Github.new :oauth_token => '...'
113
+ github.users.followers.following 'wycats' # => returns users that 'wycats' is following
114
+ github.users.followers.following 'wycats' # => returns true if following, otherwise false
121
115
  ```
122
116
 
123
117
  For specification on all available methods go to http://developer.github.com/v3/ or
124
- read the rdoc, all methods are documented there with examples of usage. Alternatively,
125
- you can find out supported methods by issuing the following in your `irb`:
118
+ read the rdoc, all methods are documented there with examples of usage. Alternatively, you can find out about supported methods by issuing the following in your `irb`:
126
119
 
127
120
  ```ruby
128
121
  >> Github::Repos.actions
@@ -140,19 +133,19 @@ Some API methods apart from required parameters such as username, repository nam
140
133
  or organisation name, allow you to switch the way the data is returned to you, for instance
141
134
 
142
135
  ```ruby
143
- @github = Github.new
144
- @github.git_data.tree 'peter-murach', 'github', 'c18647b75d72f19c1e0cc8af031e5d833b7f12ea'
136
+ github = Github.new
137
+ github.git_data.trees.get 'peter-murach', 'github', 'c18647b75d72f19c1e0cc8af031e5d833b7f12ea'
145
138
  # => gets a tree
146
139
 
147
- @github.git_data.tree 'peter-murach', 'github', 'c18647b75d72f19c1e0cc8af031e5d833b7f12ea', :recursive => true
140
+ github.git_data.trees.get 'peter-murach', 'github', 'c18647b75d72f19c1e0cc8af031e5d833b7f12ea', recursive: true
148
141
  # => gets a whole tree recursively
149
142
  ```
150
143
 
151
144
  by passing a block you can iterate over the file tree
152
145
 
153
146
  ```ruby
154
- @github.git_data.tree 'peter-murach', 'github', 'c18647b75d72f19c1e0cc8af031e5d833b7f12ea',
155
- :recursive => true do |file|
147
+ github.git_data.trees.get 'peter-murach', 'github', 'c18647b75d72f19c1e0cc8af031e5d833b7f12ea',
148
+ recursive: true do |file|
156
149
 
157
150
  puts file.path
158
151
  end
@@ -169,8 +162,8 @@ In order to authenticate the user through OAuth2 on GitHub you need to
169
162
  You can use convenience methods to help you achieve this that come with this gem:
170
163
 
171
164
  ```ruby
172
- @github = Github.new :client_id => '...', :client_secret => '...'
173
- @github.authorize_url :redirect_uri => 'http://localhost', :scope => 'repo'
165
+ github = Github.new :client_id => '...', :client_secret => '...'
166
+ github.authorize_url :redirect_uri => 'http://localhost', :scope => 'repo'
174
167
  # => "https://github.com/login/oauth/authorize?scope=repo&response_type=code&client_id='...'&redirect_uri=http%3A%2F%2Flocalhost"
175
168
  ```
176
169
  After you get your authorization code, call to receive your access_token
@@ -181,14 +174,16 @@ token = github.get_token( authorization_code )
181
174
 
182
175
  Once you have your access token, configure your github instance following instructions under Configuration.
183
176
 
177
+ ### Authorizations API
178
+
184
179
  Alternatively you can use OAuth Authorizations API. For instance, to create access token through GitHub API do following
185
180
 
186
181
  ```ruby
187
- @github = Github.new :basic_auth => 'login:password'
188
- @github.oauth.create_authorization 'scopes' => ['repo']
182
+ github = Github.new basic_auth: 'login:password'
183
+ github.oauth.create 'scopes' => ['repo']
189
184
  ```
190
185
 
191
- You can add more than one scope from the <tt>user</tt>, <tt>public_repo</tt>, <tt>repo</tt>, <tt>gist</tt> or leave the scopes parameter out, in which case, the default read-only access will be assumed(includes public user profile info, public repo info, and gists).
186
+ You can add more than one scope from the `user`, `public_repo`, `repo`, `gist` or leave the scopes parameter out, in which case, the default read-only access will be assumed(includes public user profile info, public repo info, and gists).
192
187
 
193
188
  ## MIME Types
194
189
 
@@ -197,8 +192,8 @@ Issues, PullRequests and few other API leverage custom mime types which are <tt>
197
192
  In order to pass a mime type with your request do
198
193
 
199
194
  ```ruby
200
- @github = Github.new
201
- @github.pull_requests.pull_requests 'peter-murach', 'github', :mime_type => :full
195
+ github = Github.new
196
+ github.pull_requests.list 'peter-murach', 'github', :mime_type => :full
202
197
  ```
203
198
 
204
199
  Your header will contain 'Accept: "application/vnd.github-pull.full+json"' which in turn returns raw, text and html representations in response body.
@@ -223,18 +218,32 @@ Github.new(:basic_auth => 'login:password')
223
218
 
224
219
  All parameters can be overwirtten as per method call. By passing parameters hash...
225
220
 
226
- ## Caching
221
+ ## Stack
222
+
223
+ By default the `github_api` gem will use the default middleware stack. However, a simple DSL is provided to create a custom stack, for instance:
224
+
225
+ ```ruby
226
+ github = Github.stack do
227
+ request :filter
228
+ request :normalizer
229
+ request :validations
230
+
231
+ response :cache do
232
+ register :filestore
233
+ end
227
234
 
228
- Each `get` request by default is not going to be cached. In order to set the cache do... If no cache type is provided a default memoization is done.
235
+ adapter :net_http
236
+ end
237
+ ```
229
238
 
230
- Github.cache do...
239
+ By default no caching will be performed. In order to set the cache do... If no cache type is provided a default memoization is done.
231
240
 
232
241
  ## Pagination
233
242
 
234
- Any request that returns multiple items will be paginated to 30 items by default. You can specify custom <tt>:page</tt> and <tt>:per_page</tt> query parameters to alter default behavior. For instance:
243
+ Any request that returns multiple items will be paginated to 30 items by default. You can specify custom `:page` and `:per_page` query parameters to alter default behavior. For instance:
235
244
 
236
245
  ```ruby
237
- res = Github::Repos.new.repos :user => 'wycats', :per_page => 10
246
+ res = Github::Repos.new.repos user: 'wycats', per_page: 10
238
247
  ```
239
248
 
240
249
  Then you can query pagination information included in the link header by:
@@ -291,22 +300,22 @@ res.content_type # "application/json; charset=utf-8"
291
300
  Some api methods require input parameters, these are added simply as a hash properties, for instance
292
301
 
293
302
  ```ruby
294
- @issues = Github::Issues.new :user => 'peter-murach', :repo => 'github-api'
295
- @issues.milestones :state => 'open', :sort => 'due_date', :direction => 'asc'
303
+ issues = Github::Issues.new user:'peter-murach', repo: 'github-api'
304
+ issues.milestones.list state: 'open', sort: 'due_date', direction: 'asc'
296
305
  ```
297
306
 
298
307
  Other methods may require inputs as an array of strings
299
308
 
300
309
  ```ruby
301
- @users = Github::Users.new :oauth_token => '...'
302
- @users.add_email 'email1', 'email2', ..., 'emailn' # => Adds emails to the authenticated user
310
+ users = Github::Users.new oauth_token: 'token'
311
+ users.emails.add 'email1', 'email2', ..., 'emailn' # => Adds emails to the authenticated user
303
312
  ```
304
313
 
305
314
  If a method returns a collection, you can iterator over it by supplying a block parameter,
306
315
 
307
316
  ```ruby
308
- @issues = Github::Issues.new :user => 'peter-murach', :repo => 'github-api'
309
- @issues.events do |event|
317
+ events = Github::Events.new
318
+ events.public do |event|
310
319
  puts event.actor.login
311
320
  end
312
321
  ```
@@ -314,8 +323,8 @@ end
314
323
  Query requests instead of http responses return boolean values
315
324
 
316
325
  ```ruby
317
- @github = Github.new
318
- @github.orgs.public_member? 'github', 'technoweenie' # => true
326
+ github = Github.new
327
+ github.orgs.members.public_member? 'github', 'technoweenie' # => true
319
328
  ```
320
329
 
321
330
  ## Rails Example
@@ -339,11 +348,6 @@ class GithubController < ApplicationController
339
348
  end
340
349
  ```
341
350
 
342
- ## TODO
343
-
344
- * Add request caching - local filestore?, http caching?.
345
- * Add live api tests
346
-
347
351
  ## Development
348
352
 
349
353
  Questions or problems? Please post them on the [issue tracker](https://github.com/peter-murach/github/issues). You can contribute changes by forking the project and submitting a pull request. You can ensure the tests are passing by running `bundle` and `rake`.
@@ -0,0 +1,48 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.github.com/gists/1738161/star
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ""
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 404
19
+ message: Not Found
20
+ headers:
21
+ Server:
22
+ - nginx/1.0.13
23
+ Date:
24
+ - Mon, 09 Apr 2012 17:36:04 GMT
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Transfer-Encoding:
28
+ - chunked
29
+ Connection:
30
+ - keep-alive
31
+ Status:
32
+ - 404 Not Found
33
+ X-Ratelimit-Limit:
34
+ - "5000"
35
+ Etag:
36
+ - "\"e66a7a6c91e2c26803f3f49feb7a883f\""
37
+ X-Ratelimit-Remaining:
38
+ - "4999"
39
+ Content-Encoding:
40
+ - gzip
41
+ body:
42
+ encoding: ASCII-8BIT
43
+ string: !binary |
44
+ H4sIAAAAAAAAA6tWyk0tLk5MT1WyUvLLL1Fwyy/NS1GqBQB8+Ys1FwAAAA==
45
+
46
+ http_version:
47
+ recorded_at: Mon, 09 Apr 2012 17:36:04 GMT
48
+ recorded_with: VCR 2.0.0
@@ -0,0 +1,193 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.github.com/repos/peter-murach/github/commits?per_page=45
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ""
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Server:
22
+ - nginx/1.0.13
23
+ Date:
24
+ - Mon, 09 Apr 2012 15:20:38 GMT
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Transfer-Encoding:
28
+ - chunked
29
+ Connection:
30
+ - keep-alive
31
+ Status:
32
+ - 200 OK
33
+ X-Ratelimit-Limit:
34
+ - "5000"
35
+ Etag:
36
+ - "\"8e48bd38fd07825d7042e895113f61a4\""
37
+ Link:
38
+ - <https://api.github.com/repos/peter-murach/github/commits?last_sha=f026bce0181b13d9d391d1a6f8cc90470d83cc5d&per_page=45&top=master>; rel="next", <https://api.github.com/repos/peter-murach/github/commits?per_page=45&sha=master>; rel="first"
39
+ X-Ratelimit-Remaining:
40
+ - "4996"
41
+ Content-Encoding:
42
+ - gzip
43
+ body:
44
+ encoding: ASCII-8BIT
45
+ string: !binary |
46
+ H4sIAAAAAAAAA+2da29byZGG/wqhxSJfxlbfLwQWm8siQLAIMJid/ZQERl8l
47
+ ZiRS4cWON5j/vm/zUDykbY77nOmzmQXOYADLlkqimlVP96mueutP/7gLm+fn
48
+ 1f5u+Y+757TbuYd0t7z7Y9o+pIXfunV4XPzq2e32afurxSYvHlb7x4N/C5vl
49
+ S8I/vnk+bF14vO/+/e6bO3fYP2625bulZ7d6wvd66b7k1w/l78USX7V2z+XH
50
+ fLva7LeLPx6/Bf41un35V0Yoe0PEG2K/J2op2VLgY70k5O7Hb+4O2/I9H/f7
51
+ l93y/t69rN72L+l+m142u/svvLDy+u67X3R3b3jgiSYaA5M6aWY55yxTYnki
52
+ RtgYHY0+hIhXtN8mvKJ//JyfWr7F7t7xnFTQhioZTMpexaBtcIppEYLJkRgv
53
+ ohEZP3P36PAbVhtgTbpfDO/GVMuOn9G/r0+bh9W6vK8X739549+7vdu+u35/
54
+ dikctuntw7b7bHn377sP77NnWGsplXAkmyAd8comEjWN0lhh/z3+2/ldZsK8
55
+ TW/dDw4u9Had9vdut0v73cVb/6/s96tn+O4OH7z+tMuP31BB3r6sH/BCf9KD
56
+ Dru0vfYgWLx+w3eriN/7ay8cBuXrhBCcMqzci9um9X53t/zTaD969VxHrfTB
57
+ YtGidiYJnWT0NlNLvAxZSmGli4rw3otqDX785me/uESNlSqw6JRLPiiNEDNR
58
+ cPh2YFw5fFZqbfoXV23w41++8q7djvsRMd/F3wBIXIXfHB0/HdbX0VHcrlu+
59
+ 6/3nD+uwTW6XFi9ujx3oKb1PT28LZJrvLmTJVNPdZUCMNttdrCfKRAd2Jh18
60
+ psp6qlnWzKjkk02MOBltFGcuVBtMtbtcLvu8u3Rb5z97d8ERRXLDaeZe0MiN
61
+ ciLDbTzhTOuchJTJO0/7M0q1QQOADwir0wGqduv75Pw0A7wFwL9LT+7vi7/u
62
+ NuuFW8fFdveSwuIhPS9ieknrmNZhlXaTEF2YpZBNiV7t5g2fF5jBA4AwOvKU
63
+ uOfMCS2Dc5SZxCQeV5gRTGeVzkSvNpiI6FfLPhP9l0F0qmmOTpAsaA542gxe
64
+ C8q5kIEGwbU03mpJnDl7UbVBA6IPCKuO6AMM5iP5aAe8dSTvUkIvh6enxTb9
65
+ 7ZB2+8W/ULPI283zYrvZfXxaPT19vC+ff4fPv9s/pnfr9OEdMjTvCvz/vP7z
66
+ +neb7TbtXjbruFo/LPabBb5ogS9a/ObbPyzKF63yKrj9CptG3mwXVz8LT9Hu
67
+ ue2Owd8w8z0VS1ZyS013jOon25Y7hpMSm0AKTijq8CCeAo5uUmDn4EGEKJIv
68
+ GZb+8ZvVGjTeMb647POOMTpgm2aYqjeA1zxltUGDDFMIVEVDaGaJU60DHFwT
69
+ QnWM3mTHjQ84F0XbP6BUGzTYzgbEfLedDTCYt7PR0XFrO+v3ohR/cit6W3au
70
+ bcrLxWs6+uLCofvwPpb81OYlbS8vI7o37d4SY6wTSNFaIpzKjjDKnbUaCdvI
71
+ g46KRTiz/pewWe+RKL5/z+/Do1s/4Ds+vH0utxCfZ73OG+6vXTwE93azLZnt
72
+ 063Kfz1uFv952Ln1Bv92dadyRC+xS6GWtO0zUnWk/b/e8X7mskuzlOeDxhd3
73
+ vPMPKO/6wAsVljQx2hulCNLuAg7GiE3eekdxtZTlP/NC5fL3ur5N+dqrxkKU
74
+ vBhDGAksWcPLlOqda/hW95effV8xIJ663WSAwRd3k9nzPo2XK8+7tY38Jsbj
75
+ k8titz/4hdvh2eh5hfzWtmlui7+h+nvKQY+ltE2fVAYEQbPbCpUYJXgkKT9b
76
+ mhiZw8nNJ0KI8EwpK7IymWl7zkpUGzR/UvnCsn+R2/Nd+Jcv8U8xNMVdOIWz
77
+ JDwNMGWlDSrKIAzyo9KqgBIL6Sx3HpcWvRdVGzR4GBgQVh2+Bxh8Ed+zA9Y4
78
+ 4E9R/JhgKiUti93j5sMk+BZ2SRvjuz4ImuE7R+Eojz6ixIMI7TlKmXLOjKUQ
79
+ Oa6gpc1BUtsHXrXBRPi+WvYZ36MfpZuevr1zqBEK2QeBwoUcIuMkisg0V4zg
80
+ 1lkFR3AS6HM51QYt8F0fVid81xvM+B7tgD+F73DY7XET0V0TLN67pxUyH+Um
81
+ IW23m2lO4yWLYpqexqt9vGEWRQSlnNfaoXKQapy+DVFCRKEFV54yj5oQSrgu
82
+ eajO16sNpsL55bLPOB8dTU1xzrlxLGcknZCT9z5nY6RIxHpLS0215rh7Ikh6
83
+ nr2o2qABzgeEVefiAwxmnI92wFs4/49NODwjE77o0uCtL327Z3qOS1/dFN7V
84
+ Ht0Q3imSxKKJ+DN6p7llVIVSRR9Q+UldFMbjOH5R4FFtMBG8r5Z9hvfo2GkK
85
+ 7xQDJago04LYiDScVkHYlKnTCVdWUjnGOHX5onK/1qABvAeE1alMqH4rmuE9
86
+ 2gFvwfu3h+eXyar2X/PgXC1F25P3gBBol0iReOblmumIMxKzMmtNYuZKENQw
87
+ GDwXy+B5yu58Zsq1BlPB+3LZZ3iPjp2m8I7URtR82UAT+qtYtBx3v5EwovCh
88
+ 0ZZoq5OifTqu2qABvAeE1akopnZnmav2Tz2VY5oSb8H7v19KuciiNEEufkgf
89
+ dwtUbx7r9x2uOfco+ZzoLC6WhDY9i1f7eMuzOCrSoiM6G9RhBO2T4U4LZbzL
90
+ MuFh2BJEA7pczzhPtQZT4fxy2Wec/zJwbjwnKSurWDBcBSIoTQZdtYZ71Inh
91
+ E1pyTVifSKk2aIDzAWHV4XyAwXwWH+2At3D+u2MZYaluTE8rlKUUtheKT9eE
92
+ dT6g89ap8Wo3b0h0wiPqCqjNPIXSwk6E1Oi0RfxFJrAlQqhAMZ/JmejVBlMR
93
+ /XLZZ6KPDqimB3RnWBZM4gFPcBzTlSk3LMGFEDjuyk2kEVUrToazF1UbNCD6
94
+ gLDqiD7AYCb6aAf8CtGPB/Sjvk53REfdyuMmLoJ7etp9s8irvy/84WHxAVo9
95
+ QP0TilreHb/4m+M5vpQrNj/Hs++pXFLauqy8OhQaUh9XV0ieQwYI4DfBoYzM
96
+ oHQMkkDopBQB7bfSsZB5L6ZQbdCe+p8v+0z90UHXlPpJZsZFyMoz/AchHOp5
97
+ YNRqa7go3Uo4QgSiey+qNmhA/QFh1VF/gMFM/dEOeIv6327RX4T7UED94ePC
98
+ p0f3frU5bDvAp+eX/cfXupdTZ27r6sUjZtA3JNtmaapdviHdLQ3ZaUY9emXQ
99
+ JeONkCoJJqCckyyNBJ3xUtvUl7tUG0xE96tln+k+Oria0h2lUQZKONBbEwZ6
100
+ dSmR7BPNKRnGZBLERYqTQ+69qNqgAd0HhNUp6V6/V810H+2At+j+XXrevEfS
101
+ fb07vLxstnv0o24PvrU8DjIz9HtilpwvBW+aa6927YYUzzYyBoFF5NRx6UVo
102
+ QLYUFWelAZxIgzKGkByF8El/dVpr0J7iny/7TPHRQdSU4iwJHzgRnCmdXEKZ
103
+ a9Jo1NY2+8ygleEo1SlFefaiaoMGFB8QVqe6l/o9aab4aAe8RfHSCFqwvV4d
104
+ kJPBlelf8bePr8oCz6u/tz6TH7HC8H/bRv5qF29Ic4oYlJJbrqyxWRE8M6Pk
105
+ DPLIgXIWpUaniPHk4jRVbTARza+Wfab56GBqSnMXPG7fjQ4K6IQeKupfRHCo
106
+ XOQO7cYuQfvIotOoP5NXGzSg+YCw6mg+wGCm+WgHvEXzqUvQj/CmZMnbVjFW
107
+ e3RDeKPdGgqVKjmUnePoRIWB5HBOTNGgcK2FXpAUWFL9UbzaYCJ4Xy37DO/R
108
+ sdMU3tlz9IEKaNZBxSYLL4iGnDxSLHAjmWLiELmn0vR6p9UGDeA9IKxO6fL6
109
+ rWiG92gHvAXvYwl60Rp+j1kOaAGd5ORd0rJtT97VHt0Q3k4ZaajMNGqvqSvt
110
+ 2MxHj5JFiztO9BKV3g/JLsaS1BpMBO+rZZ/hPTp2msKbaSdFJjmg2QwqEMin
111
+ cBmdVhgAkimUhkNGpRQhF3mUWoMG8B4QVh28BxjM8B7tgLfgfcqGb55KOUuZ
112
+ 8oOCxWkATpcCY6YazpUaEAbNeoiChQhLjpqgroxzjWIVVJsrgTiEhgb6PzHK
113
+ CvecpO/+qDaYCuCXyz4DfHT8NAV48AS1TgQqkTQA47gEZ1D2KRA3jMZMGINK
114
+ Kb3oRKs2aADwAWF1Sp3U7i5zD9EEPUTfJUC7ayE6Tv4oI/lW+8324wQU10up
115
+ l6KtpFa1azc8hhNJOWYDUosic6U9dFigqmUyoYkZ5C69Q7EYekJpX2heazAJ
116
+ xT9Z9pnivwyKi4B2Tye84ryI/qO2KSjIslEGgkMZkWQuXfnk2YuqDRpQfEBY
117
+ dRQfYDAfw0c74K1j+KkT9FgrfrzOLEXlk/cOIS1+ZEuZ/9rwYF7t5w2RDq0j
118
+ hSpyGigG7VgoI0FkKypkw601xEcMnVWSQOb2HIzVBtMhvV/2GemjI6rpwRwT
119
+ v5SXqE/BE53kQnmMd+RoJ3bEWEj7oK1IoQTq4nKl2qAB0geEVYf0AQYz0kc7
120
+ 4CCkf3DbNYYxTZFiAcklYN6U5NXu3ZDkECCKAWMUNI5RSktrpc5lsGqWmK6Q
121
+ DfSRssaIzP5qqtpgKpJfLvtM8tGB1JTkEEKkCvk5hdHdAg1mRbw8Q3fTaszx
122
+ ZrkIuBTNrV7sp9qgAckHhNXpgrN+X5pJPtoBb5H89ziLb8pQoM9P5BiV7X5A
123
+ D2hpBV2Ep1VpG4qrbQr7p2kSMAIiIqIp46sdvyHjFaS2lDDRM4mZAVyihIyJ
124
+ lKF6x9G0jcDUqDJnF/Xk1QYTMf5q2WfGjw6xpownBsUq6O3HEd3HhIQeYxho
125
+ onVE6Qqe9VzGPTsRuR+3Wm3QgPEDwqpj/ACDmfGjHfAW4y8TMJNkzhlpDe5q
126
+ b24IboYx9RxDIXWiFAK4NGgiob3loIMXBbVKKmYxD7WXS6o2mAjcV8s+g3t0
127
+ 3DQFt0R3AeqcqFfZW2txBAD8EvJ1mLHOvLcslmZP32fOqw0agHtAWHXgHmAw
128
+ g3u0A9aA+zjG+nQKP86hWECRKz4h4TIB0iHOqtAQ1PQsXu3nDZFueMBxO3mO
129
+ XLlHuQqelQklghEakfrE+F+UuniRex3FaoNJkP7Jss9IHx1RTZGuVSIhobaV
130
+ hSiRkfNJqIRuBEdwE4pyV9zCBOTOe9WtaoMGSB8QVh3SBxjMSB/tgNVIf3EP
131
+ pUs//e0whSYubkGPUCHnWcGjx8liPvV95xC7+2oHb8lynTH+2hvIHiF/rstU
132
+ L7QKoc+aYva19dwxPBRb2d+CmlqD6VjeL/vM8tGh1JTlPFqUuULEPGMglaGY
133
+ PqhkNqgpp1DJRTLdaEM00f3xvNqgAcsHhFXH8gEGM8tHO2AVy7sCxVKvWLLp
134
+ yJWvwnFmXDm2vxyQQX9FfBFCn+bIDsnExnIs9cHSrApdKKVQnGCll6g1t7jP
135
+ 4jIZg35rJj3F6YsRFKGJ/nKr2mAqzF8u+4z50VHWFPNQdcDsODSeSZzWHfr3
136
+ g3bQ2/Ro4Y9CoTSdedRQXQyWrTZogPnqLeV1TOIAgxnzox3wFuZP0udd/WLB
137
+ eZHM7SoZj1qKR93cXZFn2XbyW+cNoJsaGtNLWse0DtPocKklh6BiWzXF6mho
138
+ eL536BpBWRrKYRwyNBBvwd0pJYrxgDJkVqYWcEwW1f2NV7XBROC/WvYZ/KPj
139
+ rin4M4QinAi0TH02KXiotjB0tSF14zTxBoLp2kLtrfeiaoMG4B8QVt35foDB
140
+ DP7RDvgV8JeDO8peYieMCwV0wP819/7N4tDNOZpECf2YvWFQWWybia92+YZ0
141
+ pzo7pohz0DpFN6A1SkbpHfQ4oLYYqcN86Byp6Z+7qw0movvVss90Hx1cTenO
142
+ I8peZLBMcRkw7pCgq5QTXOMY5Oe1Q3NpDpic1d/nVBs0oPuAsOroPsBgpvto
143
+ B/wK3R9WGEV3HE53zfn/U8YTspRtKx+rHb8h41GnFiXBpDpIvnCXQrIeagLU
144
+ ppRQ9hA5hhwFZOv7e7Jqg4kYf7XsM+NHh1hTxkOci+PAnlA5myHCmBKHbi5l
145
+ aEP1DrLMNsK5oArTT7uoNmjA+AFh1TF+gMHM+NEOeIvxRUn32Gm6RXp+87z6
146
+ n2NGZoLsO9pk2JK1bVCq9uuGCAe18WN10Ixn3Kh6yJ0ij8qjcyhDRtNSRKFD
147
+ QC1bP2Cs1mAShH+y7DPCR0dQU4TrTF3CYRzX89Sg9CrxiF4IlXNG+UzKQmiM
148
+ IsUUrLMXVRs0QPiAsDolYeo3pBnhox3wFsJPIl7XegEfFx9wxfrauLT5AR/j
149
+ 5nUqrjduSqp29oZcZyg/jgrBGIlh5UyFmaMOOI8cWgLIqoP5kEp1fURWG0zH
150
+ 9X7ZZ66PDqumXMcgC+qNphmHAcytxeirhHosBbFdXLWiG1VAbIhiKGk/5KLW
151
+ oAHXB4TVqXimfpeauT7aAW9x/XSriqrCRXR7d8zA4AoVd6uLdfrwWTKmK3kv
152
+ RTYTJ9wljvGtRWMGxE2zOhoZqNYQ4YXel/bMm9LURHRAe3YWVFhIgckUXOyl
153
+ BqoNJiL+1bLPxB8dcE2Jjw5UogiHzxDrIR+T8TCIEdTEQ1EdWRhMxkJP02VP
154
+ XLVBA+IPCKuO+AMMZuKPdsCvEH+zfXDrUyamS7wf707PN6lf2wQmOeUT1np+
155
+ RnUgNDzlo7gNhfDECzSlcAolEIithoiZ8RB5Ihbl8SWfQ8zFKMlag4mYf7Xs
156
+ M/NHh1xT5vsyC5EEaIbChwXTkgQohgo8EaJjLkf8CQUx6BKcT/nVBg2YPyCs
157
+ OuYPMJiZP9oBbzG/JOCf3DF54w9oV03bro+1eQU8KWOlMZCUQO7RoN3pDjQ5
158
+ bJ/ulneP+/3Lbnl/X8ru8bTxePBv8UbfH8WE719KOc+b58PWhcf77rPlj3Oj
159
+ U7VrN6R4sA5aA6rorjIjFWTXhYVWGB69oc/ubKlsSwZq7Of4qzZoT/HPl32m
160
+ +Oggakpx9MJhdG2MxBOIsMuAtibUwrMcCdqeorQYLA01mdhfxlcbNKD4gLDq
161
+ KD7AYKb4aAe8RfHXXA3mIE1ZzH6ECcNQB5TCNGR4tWO3ZDhuvkLMSLxkyLD7
162
+ TAVFAOLuSzOoPErtMSABqtQXDK81mIjhV8s+M3x0CDVleMDu7yAch2l1GC7t
163
+ kGdJ0RFfnuswSwN6ciZhNIvphyFVGzRg+ICwOpU71u9IM8NHO+BXGI7sSkmv
164
+ P6f94yY2l+o9Epxa/N+U4NVu3ZDgVrpInHIQjcmUyTILAa2ElGQdqUBaBfp8
165
+ DCepvmC92mAigl8t+0zw0QHUlOBKi4Q8HAbayqiEwGw7XJ+WKxmosEPEQmlK
166
+ XOIX4+yqDRoQfEBYdQQfYDATfLQD3iL4dwnau5vthMPsOnxjmjSmkTY8gFf7
167
+ dEN8G4IeI5IwxD2iuyiSEHH1KTiqijPR0AETDjVp/CKJWW0wFb4vl33G9+jo
168
+ aYrvbAJhPmkRKUFpC1JykSaBP1CLLpwpWqFKEXkxSrrWoAG+B4RVh+8BBjO+
169
+ RzvgbXw/b96nbojdsdqlExT4bBASBNfRXfpQvvKy73SH1Mse2usT1K8D+2Ip
170
+ +ZKifr0h9gcET7OqlwxtPiO8lpAGc0objlpHTMKjUGDXifEEzT6GJ+lew7fa
171
+ YBLsf7LsM/ZHR11T7JcptwbnBa49+kktwcQWBikKyAqIRGxkKYUMZ+on4VYb
172
+ NMD+gLA65V1q96R5hukEM0y/PeweF1314hngi7j5sC7Vjo/p6QVXol02pnVh
173
+ yxHr0H6kbdPp1b7e8DRvE7KeuLASDDK+ISeJqjPMxCOQCCu5dQ3ki6DExQS8
174
+ WoOJsH617DPWfxlY98ox1K+jYr0MSYoiRwFNaIqbF0xPshQXMyiLhQBkX9hS
175
+ a9AA6wPC6lS+Xr9Jzaf50Q546zRfClvCYbffPJ/gXoTBvqAUMw3U6VK2zbAP
176
+ CI1mZ3X0kFCIBDB0A0LjEbqrFM/ZDM2mSLmjwiUjOF3AWasPx1qDqaB+uewz
177
+ 1EfHVNOzuowYmagIKhQTVwJyQozamJS2aDl1OnJGjcJY0/6sXm3QAOoDwupU
178
+ 51K748xn9QnO6gXq3VG90Hy1fu+eVmdt9k7+q+2VKXvD9DH5Yo/iAQ2TL9Ve
179
+ 3vCUDuk9HlxCq7fB1CSdtE0oNMvJYwaelg7jzPAQTXTfHlht0BjoX1z2Gei/
180
+ DKDb6OFFOTOKTn1ULkq4EDJ5FgLt6DaC8osMuIG/mFNdbdAA6APCqgP6AIP5
181
+ lD7aAX/qlP6Q1mm7Cq+zk3armDrINz2an5GCWRtQa2xI8mr3bkhyqKwLCHVB
182
+ zstxJxRmUKaMK1MC4QAId6CWwbDIoMV+PppXG0xF8stln0k+OpCaHs1pZpBn
183
+ xO2p8JBfzxJ3MIThFOA1rlCRPzdItlAu+/LFaoMGJB8QVh3JBxjMJB/tgLdI
184
+ fipBj2kXtquX5regZ3yjAL0tvqt9uiG+U0TnB26uoL9ESMlxYhKlwJibbBnJ
185
+ 3HCjMesmqh7f1QZT4fty2Wd8j46epvjOhCkfioQXxeAVDMHllhalZlxABkuE
186
+ RgsDD0H23cTVBg3wPSCsOnwPMJjxPdoBb+H7t4fnFyi3LN5DPL11BUvHbqik
187
+ YwyGanr0rnbohuwWhqDfQzrPbQzUIaeJjAmmIVEILOUMoS4TrEdX9vnoXW0w
188
+ Cbs/WfaZ3aNDpy27DfTcUOuajUkejQqYqCJ1wmUnVNJx5ob6vsPQUnkxBqPW
189
+ oAG7B4TVqYKlfiea2T3aAX/8y/8ChxrnTMIHAQA=
190
+
191
+ http_version:
192
+ recorded_at: Mon, 09 Apr 2012 15:20:38 GMT
193
+ recorded_with: VCR 2.0.0