airbyte-source-github 2.4.0__py3-none-any.whl → 2.5.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-source-github
3
- Version: 2.4.0
3
+ Version: 2.5.0
4
4
  Summary: Source implementation for GitHub.
5
5
  Home-page: https://airbyte.com
6
6
  License: ELv2
@@ -1,25 +1,21 @@
1
1
  source_github/__init__.py,sha256=8hLLjFC1wI1mMU442Y5qCcND9qIwyhaANQwT-GAIK0s,1135
2
2
  source_github/backoff_strategies.py,sha256=H1n3xNkkrlto7MqJY-Yp0el2G5S4yuJ7z3kg6aimab0,2343
3
+ source_github/components.py,sha256=itRKcQBKfGuFdaHWty7-2dDMiGdqGi65sqKSu-EduCI,3472
3
4
  source_github/config_migrations.py,sha256=guUJAdNP-liUciVaJB4ackEEMCN4jd7bNd85QFmDNlU,3932
4
5
  source_github/constants.py,sha256=Hj3Q4y7OoU-Iff4m9gEC2CjwmWJYXhNbHVNjg8EBLmQ,238
5
6
  source_github/errors_handlers.py,sha256=y0SjYuxKo3zBRhk2kZe0NZWsKen4W9x-wD84Q0S3sjU,11211
6
7
  source_github/github_schema.py,sha256=2AXmTN_s_VqvZAR1GPqus5HhSXWokS4N7HMQQqefaYw,1600315
7
8
  source_github/graphql.py,sha256=fGuYzDynYjJOR7u3GX0t6eBJMzdFxKIp4gHP73MCpos,13518
8
- source_github/manifest.yaml,sha256=YN3ifdljGR-ZlTjWHWaVDe0QXnkfB8REOXu7L9Ezt3A,264694
9
+ source_github/manifest.yaml,sha256=6r-I4uWvDq1j-oWvDsjc7-ApwavfpJpvIHbXxjmB0h8,301531
9
10
  source_github/run.py,sha256=gfWy8TcMHa0XRwaVUyq4KmslooST38fvfCLuP5D-5Fo,2391
10
- source_github/schemas/commit_comment_reactions.json,sha256=OxGmHXvft7upViZReEOmhT1jLJcQv2O0sH9WLMY8rBo,87
11
11
  source_github/schemas/commit_comments.json,sha256=QQaGL0v4PKb0y6F_l_r79Ay-hbLRFXvYAsil_aNTcas,2164
12
12
  source_github/schemas/commits.json,sha256=d6ikqHLTBhd-loXqu6g1RBatwQnet1eo0OcTvfyLO9Y,5122
13
13
  source_github/schemas/contributor_activity.json,sha256=ZF6n5nuy2KpmZh8nvaFQUnQUzU0I6r9X_NI6LXnic18,3957
14
- source_github/schemas/issue_comment_reactions.json,sha256=OxGmHXvft7upViZReEOmhT1jLJcQv2O0sH9WLMY8rBo,87
15
14
  source_github/schemas/issue_reactions.json,sha256=8KAAPEUMZw3l6ncpSxAY3EtApvJYV0yAbwzK8ny8ass,998
16
15
  source_github/schemas/issue_timeline_events.json,sha256=LrckI6mfwnbTIJs7u45k2nr3xGuiSJAYfpdW-A4PwHY,30392
17
- source_github/schemas/project_cards.json,sha256=okmLFWBYLwH1rN0-_AjlixS9o6xmi2RZqSsY1amuWFk,2016
18
- source_github/schemas/project_columns.json,sha256=kll_DqRUlEFPhZxHn6jjWU9aCMUh4ccE_tU4xFRyBg8,1489
19
16
  source_github/schemas/projects.json,sha256=f8JQLYhNfWaB3gAv3lfrHykhKKJXkBB3XlaWoDSxU8s,1848
20
17
  source_github/schemas/projects_v2.json,sha256=lH6kYCA7vkcaIIz5xNhQuMBdjlNf-4Ezdpz1YeM39lk,3162
21
18
  source_github/schemas/pull_request_comment_reactions.json,sha256=shrzajYnEHg_UlUdn56tPjyT3xPGvw3Q3RHECVgWDjc,1038
22
- source_github/schemas/pull_request_commits.json,sha256=WICcuxUsExJQe1qlXvXVN-VvkqbjWxR_E__WKO-Ta7E,4800
23
19
  source_github/schemas/pull_request_stats.json,sha256=harNH5ha6su-2OhxszHOqDKJ34OZzUsL_4nBnaOD16o,3497
24
20
  source_github/schemas/pull_requests.json,sha256=Yp9Sq3jgpfBn0YFbcZC_sy06rlJ-AMkCbHNq90KXT_Y,12196
25
21
  source_github/schemas/releases.json,sha256=3ITMlMFML3ZSfo_EAkVajJdaS_Xxz_8V4LhL9GRwWrY,5121
@@ -33,14 +29,12 @@ source_github/schemas/shared/reaction.json,sha256=CqZDoD0tp1dqv_kCYD7RCxGABcZzrH
33
29
  source_github/schemas/shared/reactions.json,sha256=0WHitNNCAqUaX1YPQmSatWmt3LADU3QYJuPo25KOdXs,629
34
30
  source_github/schemas/shared/user.json,sha256=IkeVSNG_2qsRMV2TorrzCIKxZjNXYjG6WVyXcKQ14es,1135
35
31
  source_github/schemas/shared/user_graphql.json,sha256=gdTR-fzvWK8403eJYDlOt-7uWqtDvYQDlafOAiiw0PM,453
36
- source_github/schemas/team_members.json,sha256=aHVL7ie-lhIXDZiBySXhCJg1pdjUyfkoRnGC4mH3MRg,2518
37
- source_github/schemas/team_memberships.json,sha256=ECr0ICzCwcUVp-btBicm0EemVxiOPgTtdB3hlruNsNQ,911
38
32
  source_github/schemas/workflow_jobs.json,sha256=Kk3N3FcCYBqOdR7FYvz2nAAFtLZBuVfR8Lxg-ORD39U,3934
39
33
  source_github/schemas/workflow_runs.json,sha256=XDmIsjtzka-ItEonImD3ZATZjxRNkbFo5-MPTtZDARA,19453
40
- source_github/source.py,sha256=tLmcL07V_XebADPIEsA-CiizdwDajQY2GFMaXcFYQq0,21309
41
- source_github/streams.py,sha256=kuqcqyHXJwVXna7X4LiEoQuYVdfjgCCMRA7OfAa5TnE,89979
34
+ source_github/source.py,sha256=4de4aHDIBqVxgHL8VEgD325lfCsapeoU3dnPxIJYg_M,19916
35
+ source_github/streams.py,sha256=10-eJb5g7RkhvehdPmhnTo8KFkAt1IVLOShm9HpKuY4,59424
42
36
  source_github/utils.py,sha256=rkOk8VG6ey1xDl-9t4B99N6HrvTTPCTGhvifrKwYG9Y,706
43
- airbyte_source_github-2.4.0.dist-info/METADATA,sha256=Od16kOF7VRai9nbDLWEfmTFFFJRiVIwBo6F_6XGG1RI,1248
44
- airbyte_source_github-2.4.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
45
- airbyte_source_github-2.4.0.dist-info/entry_points.txt,sha256=gYhqVrTAZvMwuYByg0b_-o115yUFLLcfNxMrLZmiW9k,55
46
- airbyte_source_github-2.4.0.dist-info/RECORD,,
37
+ airbyte_source_github-2.5.0.dist-info/METADATA,sha256=SZiB7L8oHdGl2y-JCqoxj_ct1iEiFZjf14VMwf0rxgM,1248
38
+ airbyte_source_github-2.5.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
39
+ airbyte_source_github-2.5.0.dist-info/entry_points.txt,sha256=gYhqVrTAZvMwuYByg0b_-o115yUFLLcfNxMrLZmiW9k,55
40
+ airbyte_source_github-2.5.0.dist-info/RECORD,,
@@ -0,0 +1,83 @@
1
+ #
2
+ # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
+ #
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Any, Iterable, List, Mapping, MutableMapping
7
+
8
+ import requests
9
+
10
+ from airbyte_cdk.sources.declarative.extractors.record_extractor import RecordExtractor
11
+ from airbyte_cdk.sources.declarative.migrations.state_migration import StateMigration
12
+ from airbyte_cdk.sources.types import Config
13
+
14
+
15
+ @dataclass
16
+ class IssueTimelineEventsExtractor(RecordExtractor):
17
+ """Collapse an issue's timeline page into one record keyed by event type.
18
+
19
+ The legacy `IssueTimelineEvents.parse_response` yielded `{<event type>: <event>, ...}` per page,
20
+ the last event of each type winning, and a bare record when the body was not a list.
21
+ `repository` and `issue_number` are added by the stream's transformations.
22
+ """
23
+
24
+ config: Config
25
+ parameters: Mapping[str, Any]
26
+
27
+ def extract_records(self, response: requests.Response) -> Iterable[Mapping[str, Any]]:
28
+ try:
29
+ body = response.json()
30
+ except ValueError:
31
+ body = None
32
+ record: MutableMapping[str, Any] = {}
33
+ if isinstance(body, list):
34
+ for event in body:
35
+ if isinstance(event, Mapping) and "event" in event:
36
+ record[event["event"]] = event
37
+ yield record
38
+
39
+
40
+ @dataclass
41
+ class NestedLegacyToPerPartitionStateMigration(StateMigration):
42
+ """Migrate the nested state the Python parent-child streams wrote to per-partition state.
43
+
44
+ Legacy shape: `{repository: {<parent id>: {cursor_field: value}}}`, one more level of ids per
45
+ parent (`project_cards` nests `project_id` then `column_id`). `partition_fields` lists those id
46
+ levels, outermost first. Ids were stored as strings; the declarative partitions carry them as
47
+ the integers GitHub returns.
48
+ """
49
+
50
+ config: Config
51
+ parameters: Mapping[str, Any]
52
+ cursor_field: str
53
+ partition_fields: List[str]
54
+
55
+ def should_migrate(self, stream_state: Mapping[str, Any]) -> bool:
56
+ if not stream_state or "states" in stream_state or "state" in stream_state:
57
+ return False
58
+ return all(self._is_legacy_repository_state(value) for value in stream_state.values())
59
+
60
+ def _is_legacy_repository_state(self, node: Any, depth: int = 0) -> bool:
61
+ if not isinstance(node, Mapping) or not node:
62
+ return False
63
+ if depth == len(self.partition_fields):
64
+ return set(node) == {self.cursor_field}
65
+ return all(self._is_legacy_repository_state(child, depth + 1) for child in node.values())
66
+
67
+ def migrate(self, stream_state: Mapping[str, Any]) -> Mapping[str, Any]:
68
+ states = []
69
+ for repository, node in stream_state.items():
70
+ self._collect(node, {"repository": repository}, 0, states)
71
+ return {"states": states}
72
+
73
+ def _collect(self, node: Mapping[str, Any], partition: Mapping[str, Any], depth: int, states: List[Mapping[str, Any]]) -> None:
74
+ if depth == len(self.partition_fields):
75
+ states.append({"partition": partition, "cursor": {self.cursor_field: node[self.cursor_field]}})
76
+ return
77
+ for key, child in node.items():
78
+ child_partition = {self.partition_fields[depth]: self._to_id(key), "parent_slice": partition}
79
+ self._collect(child, child_partition, depth + 1, states)
80
+
81
+ @staticmethod
82
+ def _to_id(key: str) -> Any:
83
+ return int(key) if isinstance(key, str) and key.isdigit() else key