airbyte-source-github 1.6.0__py3-none-any.whl → 1.6.1__py3-none-any.whl

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.
Files changed (32) hide show
  1. airbyte_source_github-1.6.1.dist-info/METADATA +111 -0
  2. {airbyte_source_github-1.6.0.dist-info → airbyte_source_github-1.6.1.dist-info}/RECORD +17 -43
  3. {airbyte_source_github-1.6.0.dist-info → airbyte_source_github-1.6.1.dist-info}/WHEEL +1 -2
  4. airbyte_source_github-1.6.1.dist-info/entry_points.txt +3 -0
  5. airbyte_source_github-1.6.0.dist-info/METADATA +0 -144
  6. airbyte_source_github-1.6.0.dist-info/entry_points.txt +0 -2
  7. airbyte_source_github-1.6.0.dist-info/top_level.txt +0 -3
  8. integration_tests/__init__.py +0 -0
  9. integration_tests/abnormal_state.json +0 -237
  10. integration_tests/acceptance.py +0 -16
  11. integration_tests/configured_catalog.json +0 -435
  12. integration_tests/configured_catalog_full_refresh_test.json +0 -415
  13. integration_tests/invalid_config.json +0 -5
  14. integration_tests/sample_config.json +0 -5
  15. integration_tests/sample_state.json +0 -137
  16. unit_tests/__init__.py +0 -3
  17. unit_tests/conftest.py +0 -29
  18. unit_tests/projects_v2_pull_requests_query.json +0 -3
  19. unit_tests/pull_request_stats_query.json +0 -3
  20. unit_tests/responses/contributor_activity_response.json +0 -33
  21. unit_tests/responses/graphql_reviews_responses.json +0 -405
  22. unit_tests/responses/issue_timeline_events.json +0 -166
  23. unit_tests/responses/issue_timeline_events_response.json +0 -170
  24. unit_tests/responses/projects_v2_response.json +0 -45
  25. unit_tests/responses/pull_request_comment_reactions.json +0 -744
  26. unit_tests/responses/pull_request_stats_response.json +0 -317
  27. unit_tests/test_migrations/test_config.json +0 -8
  28. unit_tests/test_migrations/test_new_config.json +0 -8
  29. unit_tests/test_multiple_token_authenticator.py +0 -163
  30. unit_tests/test_source.py +0 -331
  31. unit_tests/test_stream.py +0 -1471
  32. unit_tests/utils.py +0 -78
@@ -1,317 +0,0 @@
1
- {
2
- "data": {
3
- "repository": {
4
- "name": "integration-test",
5
- "owner": {
6
- "login": "airbytehq"
7
- },
8
- "pullRequests": {
9
- "nodes": [
10
- {
11
- "node_id": "MDExOlB1bGxSZXF1ZXN0NzIxNDM1NTA2",
12
- "id": 721435506,
13
- "number": 5,
14
- "updated_at": "2021-08-27T15:53:14Z",
15
- "changed_files": 5,
16
- "deletions": 0,
17
- "additions": 5,
18
- "merged": false,
19
- "mergeable": "MERGEABLE",
20
- "can_be_rebased": true,
21
- "maintainer_can_modify": false,
22
- "merge_state_status": "BLOCKED",
23
- "comments": {
24
- "totalCount": 0
25
- },
26
- "commits": {
27
- "totalCount": 5
28
- },
29
- "review_comments": {
30
- "totalCount": 1,
31
- "nodes": [
32
- {
33
- "comments": {
34
- "totalCount": 0
35
- }
36
- }
37
- ]
38
- },
39
- "merged_by": null
40
- },
41
- {
42
- "node_id": "MDExOlB1bGxSZXF1ZXN0NzIxNDM1NDA3",
43
- "id": 721435407,
44
- "number": 2,
45
- "updated_at": "2021-08-27T15:53:27Z",
46
- "changed_files": 5,
47
- "deletions": 0,
48
- "additions": 5,
49
- "merged": false,
50
- "mergeable": "MERGEABLE",
51
- "can_be_rebased": true,
52
- "maintainer_can_modify": false,
53
- "merge_state_status": "BLOCKED",
54
- "comments": {
55
- "totalCount": 0
56
- },
57
- "commits": {
58
- "totalCount": 5
59
- },
60
- "review_comments": {
61
- "totalCount": 1,
62
- "nodes": [
63
- {
64
- "comments": {
65
- "totalCount": 0
66
- }
67
- }
68
- ]
69
- },
70
- "merged_by": null
71
- },
72
- {
73
- "node_id": "MDExOlB1bGxSZXF1ZXN0NzIxNDM1NDQw",
74
- "id": 721435440,
75
- "number": 3,
76
- "updated_at": "2021-08-27T16:02:49Z",
77
- "changed_files": 5,
78
- "deletions": 0,
79
- "additions": 5,
80
- "merged": true,
81
- "mergeable": "UNKNOWN",
82
- "can_be_rebased": false,
83
- "maintainer_can_modify": false,
84
- "merge_state_status": "UNKNOWN",
85
- "comments": {
86
- "totalCount": 0
87
- },
88
- "commits": {
89
- "totalCount": 5
90
- },
91
- "review_comments": {
92
- "totalCount": 1,
93
- "nodes": [
94
- {
95
- "comments": {
96
- "totalCount": 0
97
- }
98
- }
99
- ]
100
- },
101
- "merged_by": {
102
- "__typename": "User",
103
- "node_id": "MDQ6VXNlcjc0MzkwMQ==",
104
- "id": 743901,
105
- "login": "gaart",
106
- "avatar_url": "https://avatars.githubusercontent.com/u/743901?v=4",
107
- "html_url": "https://github.com/gaart",
108
- "site_admin": false
109
- }
110
- },
111
- {
112
- "node_id": "MDExOlB1bGxSZXF1ZXN0NzIxNDM1NDY2",
113
- "id": 721435466,
114
- "number": 4,
115
- "updated_at": "2021-08-31T12:01:15Z",
116
- "changed_files": 5,
117
- "deletions": 0,
118
- "additions": 5,
119
- "merged": false,
120
- "mergeable": "MERGEABLE",
121
- "can_be_rebased": true,
122
- "maintainer_can_modify": false,
123
- "merge_state_status": "BLOCKED",
124
- "comments": {
125
- "totalCount": 0
126
- },
127
- "commits": {
128
- "totalCount": 5
129
- },
130
- "review_comments": {
131
- "totalCount": 3,
132
- "nodes": [
133
- {
134
- "comments": {
135
- "totalCount": 0
136
- }
137
- },
138
- {
139
- "comments": {
140
- "totalCount": 0
141
- }
142
- },
143
- {
144
- "comments": {
145
- "totalCount": 1
146
- }
147
- }
148
- ]
149
- },
150
- "merged_by": null
151
- },
152
- {
153
- "node_id": "PR_kwDOF9hP9c4xmEi6",
154
- "id": 832063674,
155
- "number": 12,
156
- "updated_at": "2022-01-26T03:46:56Z",
157
- "changed_files": 1,
158
- "deletions": 0,
159
- "additions": 2,
160
- "merged": true,
161
- "mergeable": "UNKNOWN",
162
- "can_be_rebased": false,
163
- "maintainer_can_modify": false,
164
- "merge_state_status": "UNKNOWN",
165
- "comments": {
166
- "totalCount": 0
167
- },
168
- "commits": {
169
- "totalCount": 1
170
- },
171
- "review_comments": {
172
- "totalCount": 1,
173
- "nodes": [
174
- {
175
- "comments": {
176
- "totalCount": 0
177
- }
178
- }
179
- ]
180
- },
181
- "merged_by": {
182
- "__typename": "User",
183
- "node_id": "MDQ6VXNlcjUxNTQzMjI=",
184
- "id": 5154322,
185
- "login": "marcosmarxm",
186
- "avatar_url": "https://avatars.githubusercontent.com/u/5154322?u=92c89b82271d48f41fad03923b0a24083e049038&v=4",
187
- "html_url": "https://github.com/marcosmarxm",
188
- "site_admin": false
189
- }
190
- },
191
- {
192
- "node_id": "MDExOlB1bGxSZXF1ZXN0NzIxNDM1Mzcz",
193
- "id": 721435373,
194
- "number": 1,
195
- "updated_at": "2022-03-31T11:06:06Z",
196
- "changed_files": 5,
197
- "deletions": 0,
198
- "additions": 5,
199
- "merged": false,
200
- "mergeable": "MERGEABLE",
201
- "can_be_rebased": true,
202
- "maintainer_can_modify": false,
203
- "merge_state_status": "BLOCKED",
204
- "comments": {
205
- "totalCount": 0
206
- },
207
- "commits": {
208
- "totalCount": 5
209
- },
210
- "review_comments": {
211
- "totalCount": 1,
212
- "nodes": [
213
- {
214
- "comments": {
215
- "totalCount": 0
216
- }
217
- }
218
- ]
219
- },
220
- "merged_by": null
221
- },
222
- {
223
- "node_id": "PR_kwDOF9hP9c46s2Qa",
224
- "id": 984835098,
225
- "number": 14,
226
- "updated_at": "2022-10-04T17:41:29Z",
227
- "changed_files": 1,
228
- "deletions": 0,
229
- "additions": 1,
230
- "merged": false,
231
- "mergeable": "MERGEABLE",
232
- "can_be_rebased": true,
233
- "maintainer_can_modify": false,
234
- "merge_state_status": "BLOCKED",
235
- "comments": {
236
- "totalCount": 0
237
- },
238
- "commits": {
239
- "totalCount": 2
240
- },
241
- "review_comments": {
242
- "totalCount": 1,
243
- "nodes": [
244
- {
245
- "comments": {
246
- "totalCount": 0
247
- }
248
- }
249
- ]
250
- },
251
- "merged_by": null
252
- },
253
- {
254
- "node_id": "PR_kwDOF9hP9c41Vftv",
255
- "id": 894827375,
256
- "number": 13,
257
- "updated_at": "2023-05-03T06:50:23Z",
258
- "changed_files": 1,
259
- "deletions": 1,
260
- "additions": 1,
261
- "merged": false,
262
- "mergeable": "MERGEABLE",
263
- "can_be_rebased": true,
264
- "maintainer_can_modify": false,
265
- "merge_state_status": "BLOCKED",
266
- "comments": {
267
- "totalCount": 0
268
- },
269
- "commits": {
270
- "totalCount": 1
271
- },
272
- "review_comments": {
273
- "totalCount": 0,
274
- "nodes": []
275
- },
276
- "merged_by": null
277
- },
278
- {
279
- "node_id": "PR_kwDOF9hP9c5PqZhG",
280
- "id": 1336514630,
281
- "number": 15,
282
- "updated_at": "2023-05-04T10:07:46Z",
283
- "changed_files": 1,
284
- "deletions": 0,
285
- "additions": 1,
286
- "merged": false,
287
- "mergeable": "MERGEABLE",
288
- "can_be_rebased": false,
289
- "maintainer_can_modify": false,
290
- "merge_state_status": "BLOCKED",
291
- "comments": {
292
- "totalCount": 1
293
- },
294
- "commits": {
295
- "totalCount": 1
296
- },
297
- "review_comments": {
298
- "totalCount": 1,
299
- "nodes": [
300
- {
301
- "comments": {
302
- "totalCount": 0
303
- }
304
- }
305
- ]
306
- },
307
- "merged_by": null
308
- }
309
- ],
310
- "pageInfo": {
311
- "hasNextPage": false,
312
- "endCursor": "Y3Vyc29yOnYyOpK5MjAyMy0wNS0wNFQxMzowNzo0NiswMzowMM5PqZhG"
313
- }
314
- }
315
- }
316
- }
317
- }
@@ -1,8 +0,0 @@
1
- {
2
- "credentials": {
3
- "personal_access_token": "personal_access_token"
4
- },
5
- "repository": "airbytehq/airbyte airbytehq/airbyte-platform",
6
- "start_date": "2000-01-01T00:00:00Z",
7
- "branch": "airbytehq/airbyte/master airbytehq/airbyte-platform/main"
8
- }
@@ -1,8 +0,0 @@
1
- {
2
- "credentials": {
3
- "personal_access_token": "personal_access_token"
4
- },
5
- "repositories": ["airbytehq/airbyte", "airbytehq/airbyte-platform"],
6
- "start_date": "2000-01-01T00:00:00Z",
7
- "branches": ["airbytehq/airbyte/master", "airbytehq/airbyte-platform/main"]
8
- }
@@ -1,163 +0,0 @@
1
- #
2
- # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
- #
4
-
5
- import json
6
- from unittest.mock import patch
7
-
8
- import pendulum
9
- import pytest
10
- import responses
11
- from airbyte_cdk.utils import AirbyteTracedException
12
- from freezegun import freeze_time
13
- from source_github import SourceGithub
14
- from source_github.streams import Organizations
15
- from source_github.utils import MultipleTokenAuthenticatorWithRateLimiter, read_full_refresh
16
-
17
-
18
- @responses.activate
19
- def test_multiple_tokens(rate_limit_mock_response):
20
- authenticator = SourceGithub()._get_authenticator({"access_token": "token_1, token_2, token_3"})
21
- assert isinstance(authenticator, MultipleTokenAuthenticatorWithRateLimiter)
22
- assert ["token_1", "token_2", "token_3"] == list(authenticator._tokens)
23
-
24
-
25
- @responses.activate
26
- def test_authenticator_counter(rate_limit_mock_response):
27
- """
28
- This test ensures that the rate limiter:
29
- 1. correctly handles the available limits from GitHub API and saves it.
30
- 2. correctly counts the number of requests made.
31
- """
32
- authenticator = MultipleTokenAuthenticatorWithRateLimiter(tokens=["token1", "token2", "token3"])
33
-
34
- assert [(x.count_rest, x.count_graphql) for x in authenticator._tokens.values()] == [(5000, 5000), (5000, 5000), (5000, 5000)]
35
- organization_args = {"organizations": ["org1", "org2"], "authenticator": authenticator}
36
- stream = Organizations(**organization_args)
37
- responses.add("GET", "https://api.github.com/orgs/org1", json={"id": 1})
38
- responses.add("GET", "https://api.github.com/orgs/org2", json={"id": 2})
39
- list(read_full_refresh(stream))
40
- assert authenticator._tokens["token1"].count_rest == 4998
41
-
42
-
43
- @responses.activate
44
- def test_multiple_token_authenticator_with_rate_limiter():
45
- """
46
- This test ensures that:
47
- 1. The rate limiter iterates over all tokens one-by-one after the previous is fully drained.
48
- 2. Counter is set to zero after 1500 requests were made. (500 available requests per key were set as default)
49
- 3. Exception is handled and log warning message could be found in output. Connector does not raise AirbyteTracedException because there might be GraphQL streams with remaining request we still can read.
50
- """
51
-
52
- counter_rate_limits = 0
53
- counter_orgs = 0
54
-
55
- def request_callback_rate_limits(request):
56
- nonlocal counter_rate_limits
57
- while counter_rate_limits < 3:
58
- counter_rate_limits += 1
59
- resp_body = {
60
- "resources": {
61
- "core": {
62
- "limit": 500,
63
- "used": 0,
64
- "remaining": 500,
65
- "reset": 4070908800
66
- },
67
- "graphql": {
68
- "limit": 500,
69
- "used": 0,
70
- "remaining": 500,
71
- "reset": 4070908800
72
- }
73
- }
74
- }
75
- return (200, {}, json.dumps(resp_body))
76
-
77
- responses.add_callback(responses.GET, "https://api.github.com/rate_limit", callback=request_callback_rate_limits)
78
- authenticator = MultipleTokenAuthenticatorWithRateLimiter(tokens=["token1", "token2", "token3"])
79
- organization_args = {"organizations": ["org1"], "authenticator": authenticator}
80
- stream = Organizations(**organization_args)
81
-
82
- def request_callback_orgs(request):
83
- nonlocal counter_orgs
84
- while counter_orgs < 1_501:
85
- counter_orgs += 1
86
- resp_body = {"id": 1}
87
- headers = {"Link": '<https://api.github.com/orgs/org1?page=2>; rel="next"'}
88
- return (200, headers, json.dumps(resp_body))
89
-
90
- responses.add_callback(
91
- responses.GET,
92
- "https://api.github.com/orgs/org1",
93
- callback=request_callback_orgs,
94
- content_type="application/json",
95
- )
96
- with pytest.raises(AirbyteTracedException) as e:
97
- list(read_full_refresh(stream))
98
- assert [(x.count_rest, x.count_graphql) for x in authenticator._tokens.values()] == [(0, 500), (0, 500), (0, 500)]
99
- message = "Stream: `organizations`, slice: `{'organization': 'org1'}`. Limits for all provided tokens are reached, please try again later"
100
- assert e.value.internal_message == message
101
-
102
-
103
- @freeze_time("2021-01-01 12:00:00")
104
- @responses.activate
105
- @patch("time.sleep")
106
- def test_multiple_token_authenticator_with_rate_limiter_and_sleep(sleep_mock, caplog):
107
- """
108
- This test ensures that:
109
- 1. The rate limiter will only wait (sleep) for token availability if the nearest available token appears within 600 seconds (see max_time).
110
- 2. Token Counter is reset to new values after 1500 requests were made and last token is still in use.
111
- """
112
-
113
- counter_rate_limits = 0
114
- counter_orgs = 0
115
- ACCEPTED_WAITING_TIME_IN_SECONDS = 595
116
- reset_time = (pendulum.now() + pendulum.duration(seconds=ACCEPTED_WAITING_TIME_IN_SECONDS)).int_timestamp
117
-
118
- def request_callback_rate_limits(request):
119
- nonlocal counter_rate_limits
120
- while counter_rate_limits < 6:
121
- counter_rate_limits += 1
122
- resp_body = {
123
- "resources": {
124
- "core": {
125
- "limit": 500,
126
- "used": 0,
127
- "remaining": 500,
128
- "reset": reset_time
129
- },
130
- "graphql": {
131
- "limit": 500,
132
- "used": 0,
133
- "remaining": 500,
134
- "reset": reset_time
135
- }
136
- }
137
- }
138
- return (200, {}, json.dumps(resp_body))
139
-
140
- responses.add_callback(responses.GET, "https://api.github.com/rate_limit", callback=request_callback_rate_limits)
141
- authenticator = MultipleTokenAuthenticatorWithRateLimiter(tokens=["token1", "token2", "token3"])
142
- organization_args = {"organizations": ["org1"], "authenticator": authenticator}
143
- stream = Organizations(**organization_args)
144
-
145
- def request_callback_orgs(request):
146
- nonlocal counter_orgs
147
- while counter_orgs < 1_501:
148
- counter_orgs += 1
149
- resp_body = {"id": 1}
150
- headers = {"Link": '<https://api.github.com/orgs/org1?page=2>; rel="next"'}
151
- return (200, headers, json.dumps(resp_body))
152
- return (200, {}, json.dumps({"id": 2}))
153
-
154
- responses.add_callback(
155
- responses.GET,
156
- "https://api.github.com/orgs/org1",
157
- callback=request_callback_orgs,
158
- content_type="application/json",
159
- )
160
-
161
- list(read_full_refresh(stream))
162
- sleep_mock.assert_called_once_with(ACCEPTED_WAITING_TIME_IN_SECONDS)
163
- assert [(x.count_rest, x.count_graphql) for x in authenticator._tokens.values()] == [(500, 500), (500, 500), (498, 500)]