ingestr 0.13.75__py3-none-any.whl → 0.14.98__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.
Potentially problematic release.
This version of ingestr might be problematic. Click here for more details.
- ingestr/main.py +22 -3
- ingestr/src/adjust/__init__.py +4 -4
- ingestr/src/allium/__init__.py +128 -0
- ingestr/src/anthropic/__init__.py +277 -0
- ingestr/src/anthropic/helpers.py +525 -0
- ingestr/src/appstore/__init__.py +1 -0
- ingestr/src/asana_source/__init__.py +1 -1
- ingestr/src/buildinfo.py +1 -1
- ingestr/src/chess/__init__.py +1 -1
- ingestr/src/couchbase_source/__init__.py +118 -0
- ingestr/src/couchbase_source/helpers.py +135 -0
- ingestr/src/cursor/__init__.py +83 -0
- ingestr/src/cursor/helpers.py +188 -0
- ingestr/src/destinations.py +169 -1
- ingestr/src/docebo/__init__.py +589 -0
- ingestr/src/docebo/client.py +435 -0
- ingestr/src/docebo/helpers.py +97 -0
- ingestr/src/elasticsearch/helpers.py +138 -0
- ingestr/src/errors.py +8 -0
- ingestr/src/facebook_ads/__init__.py +26 -23
- ingestr/src/facebook_ads/helpers.py +47 -1
- ingestr/src/factory.py +48 -0
- ingestr/src/filesystem/__init__.py +8 -3
- ingestr/src/filters.py +9 -0
- ingestr/src/fluxx/__init__.py +9906 -0
- ingestr/src/fluxx/helpers.py +209 -0
- ingestr/src/frankfurter/__init__.py +157 -163
- ingestr/src/frankfurter/helpers.py +3 -3
- ingestr/src/freshdesk/__init__.py +25 -8
- ingestr/src/freshdesk/freshdesk_client.py +40 -5
- ingestr/src/fundraiseup/__init__.py +49 -0
- ingestr/src/fundraiseup/client.py +81 -0
- ingestr/src/github/__init__.py +6 -4
- ingestr/src/google_analytics/__init__.py +1 -1
- ingestr/src/hostaway/__init__.py +302 -0
- ingestr/src/hostaway/client.py +288 -0
- ingestr/src/http/__init__.py +35 -0
- ingestr/src/http/readers.py +114 -0
- ingestr/src/hubspot/__init__.py +6 -12
- ingestr/src/influxdb/__init__.py +1 -0
- ingestr/src/intercom/__init__.py +142 -0
- ingestr/src/intercom/helpers.py +674 -0
- ingestr/src/intercom/settings.py +279 -0
- ingestr/src/jira_source/__init__.py +340 -0
- ingestr/src/jira_source/helpers.py +439 -0
- ingestr/src/jira_source/settings.py +170 -0
- ingestr/src/klaviyo/__init__.py +5 -5
- ingestr/src/linear/__init__.py +553 -116
- ingestr/src/linear/helpers.py +77 -38
- ingestr/src/mailchimp/__init__.py +126 -0
- ingestr/src/mailchimp/helpers.py +226 -0
- ingestr/src/mailchimp/settings.py +164 -0
- ingestr/src/masking.py +344 -0
- ingestr/src/monday/__init__.py +246 -0
- ingestr/src/monday/helpers.py +392 -0
- ingestr/src/monday/settings.py +328 -0
- ingestr/src/mongodb/__init__.py +5 -2
- ingestr/src/mongodb/helpers.py +384 -10
- ingestr/src/plusvibeai/__init__.py +335 -0
- ingestr/src/plusvibeai/helpers.py +544 -0
- ingestr/src/plusvibeai/settings.py +252 -0
- ingestr/src/revenuecat/__init__.py +83 -0
- ingestr/src/revenuecat/helpers.py +237 -0
- ingestr/src/salesforce/__init__.py +15 -8
- ingestr/src/shopify/__init__.py +1 -1
- ingestr/src/smartsheets/__init__.py +33 -5
- ingestr/src/socrata_source/__init__.py +83 -0
- ingestr/src/socrata_source/helpers.py +85 -0
- ingestr/src/socrata_source/settings.py +8 -0
- ingestr/src/sources.py +1418 -54
- ingestr/src/stripe_analytics/__init__.py +2 -19
- ingestr/src/wise/__init__.py +68 -0
- ingestr/src/wise/client.py +63 -0
- ingestr/tests/unit/test_smartsheets.py +6 -9
- {ingestr-0.13.75.dist-info → ingestr-0.14.98.dist-info}/METADATA +24 -12
- {ingestr-0.13.75.dist-info → ingestr-0.14.98.dist-info}/RECORD +79 -37
- {ingestr-0.13.75.dist-info → ingestr-0.14.98.dist-info}/WHEEL +0 -0
- {ingestr-0.13.75.dist-info → ingestr-0.14.98.dist-info}/entry_points.txt +0 -0
- {ingestr-0.13.75.dist-info → ingestr-0.14.98.dist-info}/licenses/LICENSE.md +0 -0
|
@@ -4,9 +4,14 @@ import logging
|
|
|
4
4
|
import time
|
|
5
5
|
from typing import Any, Dict, Iterable, Optional
|
|
6
6
|
|
|
7
|
+
import pendulum
|
|
7
8
|
from dlt.common.typing import TDataItem
|
|
8
9
|
from dlt.sources.helpers import requests
|
|
9
10
|
|
|
11
|
+
from ingestr.src.errors import HTTPError
|
|
12
|
+
|
|
13
|
+
TICKETS_QUERY_MAX_PAGE = 10
|
|
14
|
+
|
|
10
15
|
|
|
11
16
|
class FreshdeskClient:
|
|
12
17
|
"""
|
|
@@ -61,13 +66,15 @@ class FreshdeskClient:
|
|
|
61
66
|
else:
|
|
62
67
|
# If the error is not a rate limit (429), raise the exception to be
|
|
63
68
|
# handled elsewhere or stop execution
|
|
64
|
-
raise
|
|
69
|
+
raise HTTPError(e) from e
|
|
65
70
|
|
|
66
71
|
def paginated_response(
|
|
67
72
|
self,
|
|
68
73
|
endpoint: str,
|
|
69
74
|
per_page: int,
|
|
70
|
-
|
|
75
|
+
start_date: pendulum.DateTime,
|
|
76
|
+
end_date: pendulum.DateTime,
|
|
77
|
+
query: Optional[str] = None,
|
|
71
78
|
) -> Iterable[TDataItem]:
|
|
72
79
|
"""
|
|
73
80
|
Fetches a paginated response from a specified endpoint.
|
|
@@ -77,6 +84,11 @@ class FreshdeskClient:
|
|
|
77
84
|
updated at the specified timestamp.
|
|
78
85
|
"""
|
|
79
86
|
page = 1
|
|
87
|
+
if query is not None:
|
|
88
|
+
query = query.replace('"', "").strip()
|
|
89
|
+
|
|
90
|
+
is_tickets_query = query and endpoint == "tickets"
|
|
91
|
+
|
|
80
92
|
while True:
|
|
81
93
|
# Construct the URL for the specific endpoint
|
|
82
94
|
url = f"{self.base_url}/{endpoint}"
|
|
@@ -88,15 +100,38 @@ class FreshdeskClient:
|
|
|
88
100
|
param_key = (
|
|
89
101
|
"updated_since" if endpoint == "tickets" else "_updated_since"
|
|
90
102
|
)
|
|
91
|
-
|
|
92
|
-
|
|
103
|
+
|
|
104
|
+
params[param_key] = start_date.to_iso8601_string()
|
|
105
|
+
|
|
106
|
+
if is_tickets_query:
|
|
107
|
+
url = f"{self.base_url}/search/tickets"
|
|
108
|
+
params = {
|
|
109
|
+
"query": f'"{query}"',
|
|
110
|
+
"page": page,
|
|
111
|
+
}
|
|
93
112
|
|
|
94
113
|
# Handle requests with rate-limiting
|
|
95
114
|
# A maximum of 300 pages (30000 tickets) will be returned.
|
|
96
115
|
response = self._request_with_rate_limit(url, params=params)
|
|
97
116
|
data = response.json()
|
|
98
117
|
|
|
118
|
+
if query and endpoint == "tickets":
|
|
119
|
+
data = data["results"]
|
|
120
|
+
|
|
99
121
|
if not data:
|
|
100
122
|
break # Stop if no data or max page limit reached
|
|
101
|
-
|
|
123
|
+
|
|
124
|
+
filtered_data = [
|
|
125
|
+
item
|
|
126
|
+
for item in data
|
|
127
|
+
if "updated_at" in item
|
|
128
|
+
and pendulum.parse(item["updated_at"]) <= end_date
|
|
129
|
+
]
|
|
130
|
+
if not filtered_data:
|
|
131
|
+
break
|
|
132
|
+
yield filtered_data
|
|
102
133
|
page += 1
|
|
134
|
+
|
|
135
|
+
# https://developers.freshdesk.com/api/#filter_tickets
|
|
136
|
+
if is_tickets_query and page > TICKETS_QUERY_MAX_PAGE:
|
|
137
|
+
break
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Fundraiseup source for ingesting donations, events, fundraisers, recurring plans, and supporters."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Generator, Iterable
|
|
4
|
+
|
|
5
|
+
import dlt
|
|
6
|
+
from dlt.sources import DltResource
|
|
7
|
+
|
|
8
|
+
from .client import FundraiseupClient
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dlt.source(name="fundraiseup", max_table_nesting=0)
|
|
12
|
+
def fundraiseup_source(api_key: str) -> Iterable[DltResource]:
|
|
13
|
+
"""
|
|
14
|
+
Return resources for Fundraiseup API.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
api_key: API key for authentication
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Iterable of DLT resources
|
|
21
|
+
"""
|
|
22
|
+
client = FundraiseupClient(api_key=api_key)
|
|
23
|
+
|
|
24
|
+
# Define available resources and their configurations
|
|
25
|
+
resources = {
|
|
26
|
+
"donations": {"write_disposition": "replace", "primary_key": "id"},
|
|
27
|
+
"events": {"write_disposition": "replace", "primary_key": "id"},
|
|
28
|
+
"fundraisers": {"write_disposition": "replace", "primary_key": "id"},
|
|
29
|
+
"recurring_plans": {"write_disposition": "replace", "primary_key": "id"},
|
|
30
|
+
"supporters": {"write_disposition": "replace", "primary_key": "id"},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
def create_resource(resource_name: str, config: Dict[str, Any]) -> DltResource:
|
|
34
|
+
"""Create a DLT resource dynamically."""
|
|
35
|
+
|
|
36
|
+
@dlt.resource(
|
|
37
|
+
name=resource_name,
|
|
38
|
+
write_disposition=config["write_disposition"],
|
|
39
|
+
primary_key=config["primary_key"],
|
|
40
|
+
)
|
|
41
|
+
def generic_resource() -> Generator[Dict[str, Any], None, None]:
|
|
42
|
+
"""Generic resource that yields batches directly."""
|
|
43
|
+
for batch in client.get_paginated_data(resource_name):
|
|
44
|
+
yield batch # type: ignore[misc]
|
|
45
|
+
|
|
46
|
+
return generic_resource()
|
|
47
|
+
|
|
48
|
+
# Return all resources
|
|
49
|
+
return [create_resource(name, config) for name, config in resources.items()]
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Fundraiseup API Client for handling authentication and paginated requests."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Iterator, Optional
|
|
4
|
+
|
|
5
|
+
from ingestr.src.http_client import create_client
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class FundraiseupClient:
|
|
9
|
+
"""Client for interacting with Fundraiseup API v1."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, api_key: str):
|
|
12
|
+
"""
|
|
13
|
+
Initialize Fundraiseup API client.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
api_key: API key for authentication
|
|
17
|
+
"""
|
|
18
|
+
self.api_key = api_key
|
|
19
|
+
self.base_url = "https://api.fundraiseup.com/v1"
|
|
20
|
+
# Use shared HTTP client with retry logic for rate limiting
|
|
21
|
+
self.client = create_client(retry_status_codes=[429, 500, 502, 503, 504])
|
|
22
|
+
|
|
23
|
+
def get_paginated_data(
|
|
24
|
+
self,
|
|
25
|
+
endpoint: str,
|
|
26
|
+
params: Optional[Dict[str, Any]] = None,
|
|
27
|
+
page_size: int = 100,
|
|
28
|
+
) -> Iterator[list[Dict[str, Any]]]:
|
|
29
|
+
"""
|
|
30
|
+
Fetch paginated data from a Fundraiseup API endpoint using cursor-based pagination.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
endpoint: API endpoint path (e.g., "donations")
|
|
34
|
+
params: Additional query parameters
|
|
35
|
+
page_size: Number of items per page (default 100)
|
|
36
|
+
|
|
37
|
+
Yields:
|
|
38
|
+
Batches of items from the API
|
|
39
|
+
"""
|
|
40
|
+
url = f"{self.base_url}/{endpoint}"
|
|
41
|
+
headers = {
|
|
42
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
43
|
+
"Content-Type": "application/json",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if params is None:
|
|
47
|
+
params = {}
|
|
48
|
+
|
|
49
|
+
params["limit"] = page_size
|
|
50
|
+
starting_after = None
|
|
51
|
+
|
|
52
|
+
while True:
|
|
53
|
+
# Add cursor for pagination if not first page
|
|
54
|
+
if starting_after:
|
|
55
|
+
params["starting_after"] = starting_after
|
|
56
|
+
|
|
57
|
+
response = self.client.get(url=url, headers=headers, params=params)
|
|
58
|
+
response.raise_for_status()
|
|
59
|
+
|
|
60
|
+
data = response.json()
|
|
61
|
+
|
|
62
|
+
# Handle both list response and object with data array
|
|
63
|
+
if isinstance(data, list):
|
|
64
|
+
items = data
|
|
65
|
+
has_more = len(items) == page_size
|
|
66
|
+
else:
|
|
67
|
+
items = data.get("data", [])
|
|
68
|
+
has_more = data.get("has_more", False)
|
|
69
|
+
|
|
70
|
+
if not items:
|
|
71
|
+
break
|
|
72
|
+
|
|
73
|
+
yield items
|
|
74
|
+
|
|
75
|
+
# Set cursor for next page
|
|
76
|
+
if has_more and items:
|
|
77
|
+
starting_after = items[-1].get("id")
|
|
78
|
+
if not starting_after:
|
|
79
|
+
break
|
|
80
|
+
else:
|
|
81
|
+
break
|
ingestr/src/github/__init__.py
CHANGED
|
@@ -72,7 +72,7 @@ def github_repo_events(
|
|
|
72
72
|
name: str,
|
|
73
73
|
access_token: str,
|
|
74
74
|
start_date: pendulum.DateTime,
|
|
75
|
-
end_date: pendulum.DateTime,
|
|
75
|
+
end_date: Optional[pendulum.DateTime] = None,
|
|
76
76
|
) -> DltResource:
|
|
77
77
|
"""Gets events for repository `name` with owner `owner` incrementally.
|
|
78
78
|
|
|
@@ -91,12 +91,14 @@ def github_repo_events(
|
|
|
91
91
|
"""
|
|
92
92
|
|
|
93
93
|
# use naming function in table name to generate separate tables for each event
|
|
94
|
-
@dlt.resource(
|
|
94
|
+
@dlt.resource(
|
|
95
|
+
primary_key="id", table_name=lambda i: i["type"], write_disposition="merge"
|
|
96
|
+
)
|
|
95
97
|
def repo_events(
|
|
96
98
|
last_created_at: dlt.sources.incremental[str] = dlt.sources.incremental(
|
|
97
99
|
"created_at",
|
|
98
100
|
initial_value=start_date.isoformat(),
|
|
99
|
-
end_value=end_date.isoformat(),
|
|
101
|
+
end_value=end_date.isoformat() if end_date else None,
|
|
100
102
|
last_value_func=max,
|
|
101
103
|
range_end="closed",
|
|
102
104
|
range_start="closed",
|
|
@@ -113,7 +115,7 @@ def github_repo_events(
|
|
|
113
115
|
end_filter = (
|
|
114
116
|
pendulum.parse(last_created_at.end_value)
|
|
115
117
|
if last_created_at.end_value
|
|
116
|
-
else
|
|
118
|
+
else pendulum.now()
|
|
117
119
|
)
|
|
118
120
|
|
|
119
121
|
for page in get_rest_pages(access_token, repos_path + "?per_page=100"):
|
|
@@ -7,7 +7,7 @@ from typing import Iterator, List, Optional, Union
|
|
|
7
7
|
import dlt
|
|
8
8
|
from dlt.common import pendulum
|
|
9
9
|
from dlt.common.typing import DictStrAny, TDataItem
|
|
10
|
-
from dlt.
|
|
10
|
+
from dlt.sources import DltResource
|
|
11
11
|
from dlt.sources.credentials import GcpOAuthCredentials, GcpServiceAccountCredentials
|
|
12
12
|
from google.analytics.data_v1beta import BetaAnalyticsDataClient
|
|
13
13
|
from google.analytics.data_v1beta.types import (
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
from typing import Iterable
|
|
2
|
+
|
|
3
|
+
import dlt
|
|
4
|
+
import pendulum
|
|
5
|
+
from dlt.common.typing import TDataItem
|
|
6
|
+
from dlt.sources import DltResource
|
|
7
|
+
|
|
8
|
+
from .client import HostawayClient
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dlt.source(max_table_nesting=0)
|
|
12
|
+
def hostaway_source(
|
|
13
|
+
api_key: str,
|
|
14
|
+
start_date: pendulum.DateTime,
|
|
15
|
+
end_date: pendulum.DateTime | None = None,
|
|
16
|
+
) -> Iterable[DltResource]:
|
|
17
|
+
"""
|
|
18
|
+
Hostaway API source for fetching listings and fee settings data.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
api_key: Hostaway API key for Bearer token authentication
|
|
22
|
+
start_date: Start date for incremental loading
|
|
23
|
+
end_date: End date for incremental loading (defaults to current time)
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
Iterable[DltResource]: DLT resources for listings and/or fee settings
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
client = HostawayClient(api_key)
|
|
30
|
+
|
|
31
|
+
@dlt.resource(
|
|
32
|
+
write_disposition="merge",
|
|
33
|
+
name="listings",
|
|
34
|
+
primary_key="id",
|
|
35
|
+
)
|
|
36
|
+
def listings(
|
|
37
|
+
datetime=dlt.sources.incremental(
|
|
38
|
+
"latestActivityOn",
|
|
39
|
+
initial_value=start_date,
|
|
40
|
+
end_value=end_date,
|
|
41
|
+
range_end="closed",
|
|
42
|
+
range_start="closed",
|
|
43
|
+
),
|
|
44
|
+
) -> Iterable[TDataItem]:
|
|
45
|
+
"""
|
|
46
|
+
Fetch listings from Hostaway API with incremental loading.
|
|
47
|
+
Uses latestActivityOn field as the incremental cursor.
|
|
48
|
+
"""
|
|
49
|
+
start_dt = datetime.last_value
|
|
50
|
+
end_dt = (
|
|
51
|
+
datetime.end_value
|
|
52
|
+
if datetime.end_value is not None
|
|
53
|
+
else pendulum.now(tz="UTC")
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
yield from client.fetch_listings(start_dt, end_dt)
|
|
57
|
+
|
|
58
|
+
@dlt.resource(
|
|
59
|
+
write_disposition="merge",
|
|
60
|
+
name="listing_fee_settings",
|
|
61
|
+
primary_key="id",
|
|
62
|
+
)
|
|
63
|
+
def listing_fee_settings(
|
|
64
|
+
datetime=dlt.sources.incremental(
|
|
65
|
+
"updatedOn",
|
|
66
|
+
initial_value=start_date,
|
|
67
|
+
end_value=end_date,
|
|
68
|
+
range_end="closed",
|
|
69
|
+
range_start="closed",
|
|
70
|
+
),
|
|
71
|
+
) -> Iterable[TDataItem]:
|
|
72
|
+
"""
|
|
73
|
+
Fetch listing fee settings from Hostaway API with incremental loading.
|
|
74
|
+
Uses updatedOn field as the incremental cursor.
|
|
75
|
+
"""
|
|
76
|
+
start_dt = datetime.last_value
|
|
77
|
+
end_dt = (
|
|
78
|
+
datetime.end_value
|
|
79
|
+
if datetime.end_value is not None
|
|
80
|
+
else pendulum.now(tz="UTC")
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
yield from client.fetch_all_listing_fee_settings(start_dt, end_dt)
|
|
84
|
+
|
|
85
|
+
@dlt.resource(
|
|
86
|
+
write_disposition="replace",
|
|
87
|
+
name="listing_agreements",
|
|
88
|
+
)
|
|
89
|
+
def listing_agreements() -> Iterable[TDataItem]:
|
|
90
|
+
"""
|
|
91
|
+
Fetch listing agreements from Hostaway API.
|
|
92
|
+
|
|
93
|
+
Note: Uses replace mode, so no incremental loading.
|
|
94
|
+
"""
|
|
95
|
+
very_old_date = pendulum.datetime(1970, 1, 1, tz="UTC")
|
|
96
|
+
now = pendulum.now(tz="UTC")
|
|
97
|
+
yield from client.fetch_all_listing_agreements(very_old_date, now)
|
|
98
|
+
|
|
99
|
+
@dlt.resource(
|
|
100
|
+
write_disposition="replace",
|
|
101
|
+
name="listing_pricing_settings",
|
|
102
|
+
)
|
|
103
|
+
def listing_pricing_settings() -> Iterable[TDataItem]:
|
|
104
|
+
"""
|
|
105
|
+
Fetch listing pricing settings from Hostaway API.
|
|
106
|
+
|
|
107
|
+
Note: Uses replace mode, so no incremental loading.
|
|
108
|
+
"""
|
|
109
|
+
very_old_date = pendulum.datetime(1970, 1, 1, tz="UTC")
|
|
110
|
+
now = pendulum.now(tz="UTC")
|
|
111
|
+
yield from client.fetch_all_listing_pricing_settings(very_old_date, now)
|
|
112
|
+
|
|
113
|
+
@dlt.resource(
|
|
114
|
+
write_disposition="replace",
|
|
115
|
+
name="cancellation_policies",
|
|
116
|
+
)
|
|
117
|
+
def cancellation_policies() -> Iterable[TDataItem]:
|
|
118
|
+
yield from client.fetch_cancellation_policies()
|
|
119
|
+
|
|
120
|
+
@dlt.resource(
|
|
121
|
+
write_disposition="replace",
|
|
122
|
+
name="cancellation_policies_airbnb",
|
|
123
|
+
)
|
|
124
|
+
def cancellation_policies_airbnb() -> Iterable[TDataItem]:
|
|
125
|
+
yield from client.fetch_cancellation_policies_airbnb()
|
|
126
|
+
|
|
127
|
+
@dlt.resource(
|
|
128
|
+
write_disposition="replace",
|
|
129
|
+
name="cancellation_policies_marriott",
|
|
130
|
+
)
|
|
131
|
+
def cancellation_policies_marriott() -> Iterable[TDataItem]:
|
|
132
|
+
yield from client.fetch_cancellation_policies_marriott()
|
|
133
|
+
|
|
134
|
+
@dlt.resource(
|
|
135
|
+
write_disposition="replace",
|
|
136
|
+
name="cancellation_policies_vrbo",
|
|
137
|
+
)
|
|
138
|
+
def cancellation_policies_vrbo() -> Iterable[TDataItem]:
|
|
139
|
+
yield from client.fetch_cancellation_policies_vrbo()
|
|
140
|
+
|
|
141
|
+
@dlt.resource(
|
|
142
|
+
write_disposition="replace",
|
|
143
|
+
name="reservations",
|
|
144
|
+
selected=False,
|
|
145
|
+
)
|
|
146
|
+
def reservations() -> Iterable[TDataItem]:
|
|
147
|
+
yield from client.fetch_reservations()
|
|
148
|
+
|
|
149
|
+
@dlt.transformer(
|
|
150
|
+
data_from=reservations,
|
|
151
|
+
write_disposition="replace",
|
|
152
|
+
name="finance_fields",
|
|
153
|
+
)
|
|
154
|
+
def finance_fields(reservation_item: TDataItem) -> Iterable[TDataItem]:
|
|
155
|
+
@dlt.defer
|
|
156
|
+
def _get_finance_field(res_id):
|
|
157
|
+
return list(client.fetch_finance_field(res_id))
|
|
158
|
+
|
|
159
|
+
reservation_id_val = reservation_item.get("id")
|
|
160
|
+
if reservation_id_val:
|
|
161
|
+
yield _get_finance_field(reservation_id_val)
|
|
162
|
+
|
|
163
|
+
@dlt.resource(
|
|
164
|
+
write_disposition="replace",
|
|
165
|
+
name="reservation_payment_methods",
|
|
166
|
+
)
|
|
167
|
+
def reservation_payment_methods() -> Iterable[TDataItem]:
|
|
168
|
+
yield from client.fetch_reservation_payment_methods()
|
|
169
|
+
|
|
170
|
+
@dlt.transformer(
|
|
171
|
+
data_from=reservations,
|
|
172
|
+
write_disposition="replace",
|
|
173
|
+
name="reservation_rental_agreements",
|
|
174
|
+
)
|
|
175
|
+
def reservation_rental_agreements(
|
|
176
|
+
reservation_item: TDataItem,
|
|
177
|
+
) -> Iterable[TDataItem]:
|
|
178
|
+
@dlt.defer
|
|
179
|
+
def _get_rental_agreement(res_id):
|
|
180
|
+
return list(client.fetch_reservation_rental_agreement(res_id))
|
|
181
|
+
|
|
182
|
+
reservation_id = reservation_item.get("id")
|
|
183
|
+
if reservation_id:
|
|
184
|
+
yield _get_rental_agreement(reservation_id)
|
|
185
|
+
|
|
186
|
+
@dlt.transformer(
|
|
187
|
+
data_from=listings,
|
|
188
|
+
write_disposition="replace",
|
|
189
|
+
name="listing_calendars",
|
|
190
|
+
)
|
|
191
|
+
def listing_calendars(listing_item: TDataItem) -> Iterable[TDataItem]:
|
|
192
|
+
@dlt.defer
|
|
193
|
+
def _get_calendar(lst_id):
|
|
194
|
+
return list(client.fetch_listing_calendar(lst_id))
|
|
195
|
+
|
|
196
|
+
listing_id_val = listing_item.get("id")
|
|
197
|
+
if listing_id_val:
|
|
198
|
+
yield _get_calendar(listing_id_val)
|
|
199
|
+
|
|
200
|
+
@dlt.resource(
|
|
201
|
+
write_disposition="replace",
|
|
202
|
+
name="conversations",
|
|
203
|
+
)
|
|
204
|
+
def conversations() -> Iterable[TDataItem]:
|
|
205
|
+
yield from client.fetch_conversations()
|
|
206
|
+
|
|
207
|
+
@dlt.resource(
|
|
208
|
+
write_disposition="replace",
|
|
209
|
+
name="message_templates",
|
|
210
|
+
)
|
|
211
|
+
def message_templates() -> Iterable[TDataItem]:
|
|
212
|
+
yield from client.fetch_message_templates()
|
|
213
|
+
|
|
214
|
+
@dlt.resource(
|
|
215
|
+
write_disposition="replace",
|
|
216
|
+
name="bed_types",
|
|
217
|
+
)
|
|
218
|
+
def bed_types() -> Iterable[TDataItem]:
|
|
219
|
+
yield from client.fetch_bed_types()
|
|
220
|
+
|
|
221
|
+
@dlt.resource(
|
|
222
|
+
write_disposition="replace",
|
|
223
|
+
name="property_types",
|
|
224
|
+
)
|
|
225
|
+
def property_types() -> Iterable[TDataItem]:
|
|
226
|
+
yield from client.fetch_property_types()
|
|
227
|
+
|
|
228
|
+
@dlt.resource(
|
|
229
|
+
write_disposition="replace",
|
|
230
|
+
name="countries",
|
|
231
|
+
)
|
|
232
|
+
def countries() -> Iterable[TDataItem]:
|
|
233
|
+
yield from client.fetch_countries()
|
|
234
|
+
|
|
235
|
+
@dlt.resource(
|
|
236
|
+
write_disposition="replace",
|
|
237
|
+
name="account_tax_settings",
|
|
238
|
+
)
|
|
239
|
+
def account_tax_settings() -> Iterable[TDataItem]:
|
|
240
|
+
yield from client.fetch_account_tax_settings()
|
|
241
|
+
|
|
242
|
+
@dlt.resource(
|
|
243
|
+
write_disposition="replace",
|
|
244
|
+
name="user_groups",
|
|
245
|
+
)
|
|
246
|
+
def user_groups() -> Iterable[TDataItem]:
|
|
247
|
+
yield from client.fetch_user_groups()
|
|
248
|
+
|
|
249
|
+
@dlt.resource(
|
|
250
|
+
write_disposition="replace",
|
|
251
|
+
name="guest_payment_charges",
|
|
252
|
+
)
|
|
253
|
+
def guest_payment_charges() -> Iterable[TDataItem]:
|
|
254
|
+
yield from client.fetch_guest_payment_charges()
|
|
255
|
+
|
|
256
|
+
@dlt.resource(
|
|
257
|
+
write_disposition="replace",
|
|
258
|
+
name="coupons",
|
|
259
|
+
)
|
|
260
|
+
def coupons() -> Iterable[TDataItem]:
|
|
261
|
+
yield from client.fetch_coupons()
|
|
262
|
+
|
|
263
|
+
@dlt.resource(
|
|
264
|
+
write_disposition="replace",
|
|
265
|
+
name="webhook_reservations",
|
|
266
|
+
)
|
|
267
|
+
def webhook_reservations() -> Iterable[TDataItem]:
|
|
268
|
+
yield from client.fetch_webhook_reservations()
|
|
269
|
+
|
|
270
|
+
@dlt.resource(
|
|
271
|
+
write_disposition="replace",
|
|
272
|
+
name="tasks",
|
|
273
|
+
)
|
|
274
|
+
def tasks() -> Iterable[TDataItem]:
|
|
275
|
+
yield from client.fetch_tasks()
|
|
276
|
+
|
|
277
|
+
return (
|
|
278
|
+
listings,
|
|
279
|
+
listing_fee_settings,
|
|
280
|
+
listing_agreements,
|
|
281
|
+
listing_pricing_settings,
|
|
282
|
+
cancellation_policies,
|
|
283
|
+
cancellation_policies_airbnb,
|
|
284
|
+
cancellation_policies_marriott,
|
|
285
|
+
cancellation_policies_vrbo,
|
|
286
|
+
reservations,
|
|
287
|
+
finance_fields,
|
|
288
|
+
reservation_payment_methods,
|
|
289
|
+
reservation_rental_agreements,
|
|
290
|
+
listing_calendars,
|
|
291
|
+
conversations,
|
|
292
|
+
message_templates,
|
|
293
|
+
bed_types,
|
|
294
|
+
property_types,
|
|
295
|
+
countries,
|
|
296
|
+
account_tax_settings,
|
|
297
|
+
user_groups,
|
|
298
|
+
guest_payment_charges,
|
|
299
|
+
coupons,
|
|
300
|
+
webhook_reservations,
|
|
301
|
+
tasks,
|
|
302
|
+
)
|