cloudquery-plugin-sdk 0.1.46__tar.gz → 0.1.48__tar.gz
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.
- {cloudquery_plugin_sdk-0.1.46/cloudquery_plugin_sdk.egg-info → cloudquery_plugin_sdk-0.1.48}/PKG-INFO +8 -8
- cloudquery_plugin_sdk-0.1.48/cloudquery/sdk/internal/memdb/memdb.py +221 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/internal/servers/plugin_v3/plugin.py +7 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/message/__init__.py +6 -1
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/message/sync.py +6 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scheduler/scheduler.py +2 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48/cloudquery_plugin_sdk.egg-info}/PKG-INFO +8 -8
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery_plugin_sdk.egg-info/requires.txt +7 -7
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/setup.py +8 -8
- cloudquery_plugin_sdk-0.1.46/cloudquery/sdk/internal/memdb/memdb.py +0 -118
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/LICENSE +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/README.md +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/internal/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/internal/memdb/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/internal/servers/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/internal/servers/discovery_v1/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/internal/servers/discovery_v1/discovery.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/internal/servers/plugin_v3/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/message/read.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/message/write.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/plugin/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/plugin/plugin.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/py.typed +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/binary.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/bool.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/date32.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/date64.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/float.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/int.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/json.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/list.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/scalar.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/scalar_factory.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/string.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/timestamp.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/uint.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/uuid.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/vector.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scheduler/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scheduler/table_resolver.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/schema/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/schema/arrow.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/schema/column.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/schema/resource.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/schema/table.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/serve/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/serve/plugin.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/stateclient/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/stateclient/stateclient.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/transformers/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/transformers/openapi.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/transformers/transformers.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/types/__init__.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/types/json.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/types/uuid.py +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery_plugin_sdk.egg-info/SOURCES.txt +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery_plugin_sdk.egg-info/dependency_links.txt +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery_plugin_sdk.egg-info/namespace_packages.txt +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery_plugin_sdk.egg-info/not-zip-safe +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery_plugin_sdk.egg-info/top_level.txt +0 -0
- {cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudquery-plugin-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.48
|
|
4
4
|
Summary: CloudQuery Plugin SDK for Python
|
|
5
5
|
Home-page: https://github.com/cloudquery/plugin-sdk-python
|
|
6
6
|
Author: CloudQuery LTD
|
|
@@ -20,25 +20,25 @@ Classifier: Operating System :: OS Independent
|
|
|
20
20
|
Classifier: Topic :: Internet
|
|
21
21
|
Requires-Python: >=3.7
|
|
22
22
|
License-File: LICENSE
|
|
23
|
-
Requires-Dist: cloudquery-plugin-pb==0.0.
|
|
23
|
+
Requires-Dist: cloudquery-plugin-pb==0.0.47
|
|
24
24
|
Requires-Dist: exceptiongroup==1.3.0
|
|
25
|
-
Requires-Dist: black==25.
|
|
26
|
-
Requires-Dist: grpcio==1.
|
|
27
|
-
Requires-Dist: grpcio-tools==1.
|
|
25
|
+
Requires-Dist: black==25.9.0
|
|
26
|
+
Requires-Dist: grpcio==1.75.0
|
|
27
|
+
Requires-Dist: grpcio-tools==1.75.0
|
|
28
28
|
Requires-Dist: iniconfig==2.1.0
|
|
29
29
|
Requires-Dist: Jinja2==3.1.6
|
|
30
30
|
Requires-Dist: MarkupSafe==3.0.2
|
|
31
|
-
Requires-Dist: numpy==2.3.
|
|
31
|
+
Requires-Dist: numpy==2.3.3
|
|
32
32
|
Requires-Dist: packaging==24.2
|
|
33
33
|
Requires-Dist: pandas==2.3.2
|
|
34
34
|
Requires-Dist: pluggy==1.6.0
|
|
35
35
|
Requires-Dist: protobuf>=6.31.1
|
|
36
36
|
Requires-Dist: pyarrow==19.0.1
|
|
37
|
-
Requires-Dist: pytest==8.4.
|
|
37
|
+
Requires-Dist: pytest==8.4.2
|
|
38
38
|
Requires-Dist: python-dateutil>=2.8.1
|
|
39
39
|
Requires-Dist: pytz==2025.2
|
|
40
40
|
Requires-Dist: six==1.17.0
|
|
41
|
-
Requires-Dist: structlog==25.
|
|
41
|
+
Requires-Dist: structlog==25.4.0
|
|
42
42
|
Requires-Dist: tomli==2.2.1
|
|
43
43
|
Requires-Dist: tzdata==2025.1
|
|
44
44
|
Dynamic: author
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from cloudquery.sdk import plugin
|
|
4
|
+
from cloudquery.sdk import message
|
|
5
|
+
from cloudquery.sdk import schema
|
|
6
|
+
from cloudquery.sdk.scheduler import Scheduler, TableResolver
|
|
7
|
+
from typing import List, Generator, Dict, Any
|
|
8
|
+
import pyarrow as pa
|
|
9
|
+
from cloudquery.sdk.schema.table import Table
|
|
10
|
+
from cloudquery.sdk.schema.arrow import METADATA_TABLE_NAME
|
|
11
|
+
from cloudquery.sdk.types import JSONType
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
|
|
14
|
+
NAME = "memdb"
|
|
15
|
+
VERSION = "development"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Client:
|
|
19
|
+
def __init__(self) -> None:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
def id(self):
|
|
23
|
+
return "memdb"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MemDBResolver(TableResolver):
|
|
27
|
+
def __init__(
|
|
28
|
+
self, table: Table, records: List, child_resolvers: list[TableResolver] = None
|
|
29
|
+
) -> None:
|
|
30
|
+
super().__init__(table=table, child_resolvers=child_resolvers)
|
|
31
|
+
self._records = records
|
|
32
|
+
|
|
33
|
+
def resolve(self, client: None, parent_resource) -> Generator[Any, None, None]:
|
|
34
|
+
for record in self._records:
|
|
35
|
+
yield record
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Table1Relation1(Table):
|
|
39
|
+
def __init__(self) -> None:
|
|
40
|
+
super().__init__(
|
|
41
|
+
name="table_1_relation_1",
|
|
42
|
+
columns=[
|
|
43
|
+
schema.Column(
|
|
44
|
+
name="name",
|
|
45
|
+
type=pa.string(),
|
|
46
|
+
primary_key=True,
|
|
47
|
+
not_null=True,
|
|
48
|
+
unique=True,
|
|
49
|
+
),
|
|
50
|
+
schema.Column(name="data", type=JSONType()),
|
|
51
|
+
],
|
|
52
|
+
title="Table 1 Relation 1",
|
|
53
|
+
description="Test Table 1 Relation 1",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def resolver(self):
|
|
58
|
+
return MemDBResolver(
|
|
59
|
+
self,
|
|
60
|
+
records=[
|
|
61
|
+
{"name": "a", "data": {"a": 1}},
|
|
62
|
+
{"name": "b", "data": {"b": 2}},
|
|
63
|
+
{"name": "c", "data": {"c": 3}},
|
|
64
|
+
],
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Table1(Table):
|
|
69
|
+
def __init__(self) -> None:
|
|
70
|
+
super().__init__(
|
|
71
|
+
name="table_1",
|
|
72
|
+
columns=[
|
|
73
|
+
schema.Column(
|
|
74
|
+
name="name",
|
|
75
|
+
type=pa.string(),
|
|
76
|
+
primary_key=True,
|
|
77
|
+
not_null=True,
|
|
78
|
+
unique=True,
|
|
79
|
+
),
|
|
80
|
+
schema.Column(
|
|
81
|
+
name="id",
|
|
82
|
+
type=pa.int64(),
|
|
83
|
+
primary_key=True,
|
|
84
|
+
not_null=True,
|
|
85
|
+
unique=True,
|
|
86
|
+
incremental_key=True,
|
|
87
|
+
),
|
|
88
|
+
],
|
|
89
|
+
title="Table 1",
|
|
90
|
+
description="Test Table 1",
|
|
91
|
+
is_incremental=True,
|
|
92
|
+
relations=[Table1Relation1()],
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def resolver(self):
|
|
97
|
+
child_resolvers: list[TableResolver] = []
|
|
98
|
+
for rel in self.relations:
|
|
99
|
+
child_resolvers.append(rel.resolver)
|
|
100
|
+
|
|
101
|
+
return MemDBResolver(
|
|
102
|
+
self,
|
|
103
|
+
records=[
|
|
104
|
+
{"name": "a", "id": 1},
|
|
105
|
+
{"name": "b", "id": 2},
|
|
106
|
+
{"name": "c", "id": 3},
|
|
107
|
+
],
|
|
108
|
+
child_resolvers=child_resolvers,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class Table2(Table):
|
|
113
|
+
def __init__(self) -> None:
|
|
114
|
+
super().__init__(
|
|
115
|
+
name="table_2",
|
|
116
|
+
columns=[
|
|
117
|
+
schema.Column(
|
|
118
|
+
name="name",
|
|
119
|
+
type=pa.string(),
|
|
120
|
+
primary_key=True,
|
|
121
|
+
not_null=True,
|
|
122
|
+
unique=True,
|
|
123
|
+
),
|
|
124
|
+
schema.Column(name="id", type=pa.int64()),
|
|
125
|
+
],
|
|
126
|
+
title="Table 2",
|
|
127
|
+
description="Test Table 2",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def resolver(self):
|
|
132
|
+
return MemDBResolver(
|
|
133
|
+
self,
|
|
134
|
+
records=[
|
|
135
|
+
{"name": "a", "id": 1},
|
|
136
|
+
{"name": "b", "id": 2},
|
|
137
|
+
{"name": "c", "id": 3},
|
|
138
|
+
],
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@dataclass
|
|
143
|
+
class Spec:
|
|
144
|
+
concurrency: int = field(default=1000)
|
|
145
|
+
queue_size: int = field(default=1000)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class MemDB(plugin.Plugin):
|
|
149
|
+
def __init__(self) -> None:
|
|
150
|
+
super().__init__(
|
|
151
|
+
NAME, VERSION, opts=plugin.plugin.Options(team="cloudquery", kind="source")
|
|
152
|
+
)
|
|
153
|
+
table1 = Table1()
|
|
154
|
+
table2 = Table2()
|
|
155
|
+
self._tables: Dict[str, schema.Table] = {
|
|
156
|
+
table1.name: table1,
|
|
157
|
+
table2.name: table2,
|
|
158
|
+
}
|
|
159
|
+
self._db: List[pa.RecordBatch] = []
|
|
160
|
+
self._client = Client()
|
|
161
|
+
|
|
162
|
+
def set_logger(self, logger) -> None:
|
|
163
|
+
self._logger = logger
|
|
164
|
+
|
|
165
|
+
def init(self, spec, no_connection: bool = False):
|
|
166
|
+
if no_connection:
|
|
167
|
+
return
|
|
168
|
+
self._spec_json = json.loads(spec)
|
|
169
|
+
self._spec = Spec(**self._spec_json)
|
|
170
|
+
self._scheduler = Scheduler(
|
|
171
|
+
concurrency=self._spec.concurrency,
|
|
172
|
+
queue_size=self._spec.queue_size,
|
|
173
|
+
logger=self._logger,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
def get_tables(self, options: plugin.TableOptions = None) -> List[plugin.Table]:
|
|
177
|
+
tables = list(self._tables.values())
|
|
178
|
+
|
|
179
|
+
# set parent table relationships
|
|
180
|
+
for table in tables:
|
|
181
|
+
for relation in table.relations:
|
|
182
|
+
relation.parent = table
|
|
183
|
+
|
|
184
|
+
return schema.filter_dfs(tables, options.tables, options.skip_tables)
|
|
185
|
+
|
|
186
|
+
def sync(
|
|
187
|
+
self, options: plugin.SyncOptions
|
|
188
|
+
) -> Generator[message.SyncMessage, None, None]:
|
|
189
|
+
resolvers: list[TableResolver] = []
|
|
190
|
+
for table in self.get_tables(
|
|
191
|
+
plugin.TableOptions(
|
|
192
|
+
tables=options.tables,
|
|
193
|
+
skip_tables=options.skip_tables,
|
|
194
|
+
skip_dependent_tables=options.skip_dependent_tables,
|
|
195
|
+
)
|
|
196
|
+
):
|
|
197
|
+
resolvers.append(table.resolver)
|
|
198
|
+
|
|
199
|
+
return self._scheduler.sync(
|
|
200
|
+
self._client, resolvers, options.deterministic_cq_id
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
def write(self, writer: Generator[message.WriteMessage, None, None]) -> None:
|
|
204
|
+
for msg in writer:
|
|
205
|
+
if isinstance(msg, message.WriteMigrateTableMessage):
|
|
206
|
+
pass
|
|
207
|
+
elif isinstance(msg, message.WriteInsertMessage):
|
|
208
|
+
self._db.append(msg.record)
|
|
209
|
+
else:
|
|
210
|
+
raise NotImplementedError(f"Unknown message type {type(msg)}")
|
|
211
|
+
|
|
212
|
+
def read(self, table: Table) -> Generator[message.ReadMessage, None, None]:
|
|
213
|
+
for record in self._db:
|
|
214
|
+
recordMetadata = record.schema.metadata.get(METADATA_TABLE_NAME).decode(
|
|
215
|
+
"utf-8"
|
|
216
|
+
)
|
|
217
|
+
if recordMetadata == table.name:
|
|
218
|
+
yield message.ReadMessage(record)
|
|
219
|
+
|
|
220
|
+
def close(self) -> None:
|
|
221
|
+
self._db = {}
|
|
@@ -7,6 +7,7 @@ from cloudquery.plugin_v3 import plugin_pb2, plugin_pb2_grpc, arrow
|
|
|
7
7
|
from cloudquery.sdk.message import (
|
|
8
8
|
SyncInsertMessage,
|
|
9
9
|
SyncMigrateTableMessage,
|
|
10
|
+
SyncErrorMessage,
|
|
10
11
|
WriteInsertMessage,
|
|
11
12
|
WriteMigrateTableMessage,
|
|
12
13
|
WriteMessage,
|
|
@@ -77,6 +78,12 @@ class PluginServicer(plugin_pb2_grpc.PluginServicer):
|
|
|
77
78
|
yield plugin_pb2.Sync.Response(
|
|
78
79
|
migrate_table=plugin_pb2.Sync.MessageMigrateTable(table=buf)
|
|
79
80
|
)
|
|
81
|
+
elif isinstance(msg, SyncErrorMessage) and request.withErrorMessages:
|
|
82
|
+
yield plugin_pb2.Sync.Response(
|
|
83
|
+
error=plugin_pb2.Sync.MessageError(
|
|
84
|
+
table_name=msg.table_name, error=msg.error
|
|
85
|
+
)
|
|
86
|
+
)
|
|
80
87
|
else:
|
|
81
88
|
# unknown sync message type
|
|
82
89
|
raise NotImplementedError()
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/message/sync.py
RENAMED
|
@@ -13,3 +13,9 @@ class SyncInsertMessage(SyncMessage):
|
|
|
13
13
|
class SyncMigrateTableMessage(SyncMessage):
|
|
14
14
|
def __init__(self, table: pa.Schema):
|
|
15
15
|
self.table = table
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SyncErrorMessage(SyncMessage):
|
|
19
|
+
def __init__(self, table_name: str, error: str):
|
|
20
|
+
self.table_name = table_name
|
|
21
|
+
self.error = error
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scheduler/scheduler.py
RENAMED
|
@@ -8,6 +8,7 @@ from cloudquery.sdk.message import (
|
|
|
8
8
|
SyncMessage,
|
|
9
9
|
SyncInsertMessage,
|
|
10
10
|
SyncMigrateTableMessage,
|
|
11
|
+
SyncErrorMessage,
|
|
11
12
|
)
|
|
12
13
|
from cloudquery.sdk.schema import Resource
|
|
13
14
|
from cloudquery.sdk.stateclient.stateclient import StateClient
|
|
@@ -162,6 +163,7 @@ class Scheduler:
|
|
|
162
163
|
depth=depth,
|
|
163
164
|
exc_info=e,
|
|
164
165
|
)
|
|
166
|
+
res.put(SyncErrorMessage(resolver.table.name, str(e)))
|
|
165
167
|
finally:
|
|
166
168
|
res.put(TableResolverFinished())
|
|
167
169
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudquery-plugin-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.48
|
|
4
4
|
Summary: CloudQuery Plugin SDK for Python
|
|
5
5
|
Home-page: https://github.com/cloudquery/plugin-sdk-python
|
|
6
6
|
Author: CloudQuery LTD
|
|
@@ -20,25 +20,25 @@ Classifier: Operating System :: OS Independent
|
|
|
20
20
|
Classifier: Topic :: Internet
|
|
21
21
|
Requires-Python: >=3.7
|
|
22
22
|
License-File: LICENSE
|
|
23
|
-
Requires-Dist: cloudquery-plugin-pb==0.0.
|
|
23
|
+
Requires-Dist: cloudquery-plugin-pb==0.0.47
|
|
24
24
|
Requires-Dist: exceptiongroup==1.3.0
|
|
25
|
-
Requires-Dist: black==25.
|
|
26
|
-
Requires-Dist: grpcio==1.
|
|
27
|
-
Requires-Dist: grpcio-tools==1.
|
|
25
|
+
Requires-Dist: black==25.9.0
|
|
26
|
+
Requires-Dist: grpcio==1.75.0
|
|
27
|
+
Requires-Dist: grpcio-tools==1.75.0
|
|
28
28
|
Requires-Dist: iniconfig==2.1.0
|
|
29
29
|
Requires-Dist: Jinja2==3.1.6
|
|
30
30
|
Requires-Dist: MarkupSafe==3.0.2
|
|
31
|
-
Requires-Dist: numpy==2.3.
|
|
31
|
+
Requires-Dist: numpy==2.3.3
|
|
32
32
|
Requires-Dist: packaging==24.2
|
|
33
33
|
Requires-Dist: pandas==2.3.2
|
|
34
34
|
Requires-Dist: pluggy==1.6.0
|
|
35
35
|
Requires-Dist: protobuf>=6.31.1
|
|
36
36
|
Requires-Dist: pyarrow==19.0.1
|
|
37
|
-
Requires-Dist: pytest==8.4.
|
|
37
|
+
Requires-Dist: pytest==8.4.2
|
|
38
38
|
Requires-Dist: python-dateutil>=2.8.1
|
|
39
39
|
Requires-Dist: pytz==2025.2
|
|
40
40
|
Requires-Dist: six==1.17.0
|
|
41
|
-
Requires-Dist: structlog==25.
|
|
41
|
+
Requires-Dist: structlog==25.4.0
|
|
42
42
|
Requires-Dist: tomli==2.2.1
|
|
43
43
|
Requires-Dist: tzdata==2025.1
|
|
44
44
|
Dynamic: author
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
cloudquery-plugin-pb==0.0.
|
|
1
|
+
cloudquery-plugin-pb==0.0.47
|
|
2
2
|
exceptiongroup==1.3.0
|
|
3
|
-
black==25.
|
|
4
|
-
grpcio==1.
|
|
5
|
-
grpcio-tools==1.
|
|
3
|
+
black==25.9.0
|
|
4
|
+
grpcio==1.75.0
|
|
5
|
+
grpcio-tools==1.75.0
|
|
6
6
|
iniconfig==2.1.0
|
|
7
7
|
Jinja2==3.1.6
|
|
8
8
|
MarkupSafe==3.0.2
|
|
9
|
-
numpy==2.3.
|
|
9
|
+
numpy==2.3.3
|
|
10
10
|
packaging==24.2
|
|
11
11
|
pandas==2.3.2
|
|
12
12
|
pluggy==1.6.0
|
|
13
13
|
protobuf>=6.31.1
|
|
14
14
|
pyarrow==19.0.1
|
|
15
|
-
pytest==8.4.
|
|
15
|
+
pytest==8.4.2
|
|
16
16
|
python-dateutil>=2.8.1
|
|
17
17
|
pytz==2025.2
|
|
18
18
|
six==1.17.0
|
|
19
|
-
structlog==25.
|
|
19
|
+
structlog==25.4.0
|
|
20
20
|
tomli==2.2.1
|
|
21
21
|
tzdata==2025.1
|
|
@@ -10,25 +10,25 @@ name = "cloudquery-plugin-sdk"
|
|
|
10
10
|
description = "CloudQuery Plugin SDK for Python"
|
|
11
11
|
|
|
12
12
|
dependencies = [
|
|
13
|
-
"cloudquery-plugin-pb==0.0.
|
|
13
|
+
"cloudquery-plugin-pb==0.0.47",
|
|
14
14
|
"exceptiongroup==1.3.0",
|
|
15
|
-
"black==25.
|
|
16
|
-
"grpcio==1.
|
|
17
|
-
"grpcio-tools==1.
|
|
15
|
+
"black==25.9.0",
|
|
16
|
+
"grpcio==1.75.0",
|
|
17
|
+
"grpcio-tools==1.75.0",
|
|
18
18
|
"iniconfig==2.1.0",
|
|
19
19
|
"Jinja2==3.1.6",
|
|
20
20
|
"MarkupSafe==3.0.2",
|
|
21
|
-
"numpy==2.3.
|
|
21
|
+
"numpy==2.3.3",
|
|
22
22
|
"packaging==24.2",
|
|
23
23
|
"pandas==2.3.2",
|
|
24
24
|
"pluggy==1.6.0",
|
|
25
25
|
"protobuf>=6.31.1",
|
|
26
26
|
"pyarrow==19.0.1",
|
|
27
|
-
"pytest==8.4.
|
|
27
|
+
"pytest==8.4.2",
|
|
28
28
|
"python-dateutil>=2.8.1",
|
|
29
29
|
"pytz==2025.2",
|
|
30
30
|
"six==1.17.0",
|
|
31
|
-
"structlog==25.
|
|
31
|
+
"structlog==25.4.0",
|
|
32
32
|
"tomli==2.2.1",
|
|
33
33
|
"tzdata==2025.1",
|
|
34
34
|
]
|
|
@@ -51,7 +51,7 @@ packages = [
|
|
|
51
51
|
]
|
|
52
52
|
setuptools.setup(
|
|
53
53
|
name=name,
|
|
54
|
-
version="0.1.
|
|
54
|
+
version="0.1.48",
|
|
55
55
|
description=description,
|
|
56
56
|
long_description=long_description,
|
|
57
57
|
author="CloudQuery LTD",
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
from cloudquery.sdk import plugin
|
|
4
|
-
from cloudquery.sdk import message
|
|
5
|
-
from cloudquery.sdk import schema
|
|
6
|
-
from typing import List, Generator, Dict
|
|
7
|
-
import pyarrow as pa
|
|
8
|
-
from cloudquery.sdk.schema.table import Table
|
|
9
|
-
from cloudquery.sdk.types import JSONType
|
|
10
|
-
from dataclasses import dataclass, field
|
|
11
|
-
|
|
12
|
-
NAME = "memdb"
|
|
13
|
-
VERSION = "development"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@dataclass
|
|
17
|
-
class Spec:
|
|
18
|
-
abc: str = field(default="abc")
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class MemDB(plugin.Plugin):
|
|
22
|
-
def __init__(self) -> None:
|
|
23
|
-
super().__init__(
|
|
24
|
-
NAME, VERSION, opts=plugin.plugin.Options(team="cloudquery", kind="source")
|
|
25
|
-
)
|
|
26
|
-
self._db: Dict[str, pa.RecordBatch] = {}
|
|
27
|
-
self._tables: Dict[str, schema.Table] = {
|
|
28
|
-
"table_1": schema.Table(
|
|
29
|
-
name="table_1",
|
|
30
|
-
columns=[
|
|
31
|
-
schema.Column(
|
|
32
|
-
name="name",
|
|
33
|
-
type=pa.string(),
|
|
34
|
-
primary_key=True,
|
|
35
|
-
not_null=True,
|
|
36
|
-
unique=True,
|
|
37
|
-
),
|
|
38
|
-
schema.Column(
|
|
39
|
-
name="id",
|
|
40
|
-
type=pa.string(),
|
|
41
|
-
primary_key=True,
|
|
42
|
-
not_null=True,
|
|
43
|
-
unique=True,
|
|
44
|
-
incremental_key=True,
|
|
45
|
-
),
|
|
46
|
-
],
|
|
47
|
-
title="Table 1",
|
|
48
|
-
description="Test Table 1",
|
|
49
|
-
is_incremental=True,
|
|
50
|
-
relations=[
|
|
51
|
-
schema.Table(
|
|
52
|
-
name="table_1_relation_1",
|
|
53
|
-
columns=[
|
|
54
|
-
schema.Column(
|
|
55
|
-
name="name",
|
|
56
|
-
type=pa.string(),
|
|
57
|
-
primary_key=True,
|
|
58
|
-
not_null=True,
|
|
59
|
-
unique=True,
|
|
60
|
-
),
|
|
61
|
-
schema.Column(name="data", type=JSONType()),
|
|
62
|
-
],
|
|
63
|
-
title="Table 1 Relation 1",
|
|
64
|
-
description="Test Table 1 Relation 1",
|
|
65
|
-
)
|
|
66
|
-
],
|
|
67
|
-
),
|
|
68
|
-
"table_2": schema.Table(
|
|
69
|
-
name="table_2",
|
|
70
|
-
columns=[
|
|
71
|
-
schema.Column(
|
|
72
|
-
name="name",
|
|
73
|
-
type=pa.string(),
|
|
74
|
-
primary_key=True,
|
|
75
|
-
not_null=True,
|
|
76
|
-
unique=True,
|
|
77
|
-
),
|
|
78
|
-
schema.Column(name="id", type=pa.string()),
|
|
79
|
-
],
|
|
80
|
-
title="Table 2",
|
|
81
|
-
description="Test Table 2",
|
|
82
|
-
),
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
def init(self, spec, no_connection: bool = False):
|
|
86
|
-
if no_connection:
|
|
87
|
-
return
|
|
88
|
-
self._spec_json = json.loads(spec)
|
|
89
|
-
self._spec = Spec(**self._spec_json)
|
|
90
|
-
|
|
91
|
-
def get_tables(self, options: plugin.TableOptions = None) -> List[plugin.Table]:
|
|
92
|
-
tables = list(self._tables.values())
|
|
93
|
-
return schema.filter_dfs(tables, options.tables, options.skip_tables)
|
|
94
|
-
|
|
95
|
-
def sync(
|
|
96
|
-
self, options: plugin.SyncOptions
|
|
97
|
-
) -> Generator[message.SyncMessage, None, None]:
|
|
98
|
-
for table, record in self._db.items():
|
|
99
|
-
yield message.SyncInsertMessage(record)
|
|
100
|
-
|
|
101
|
-
def write(self, writer: Generator[message.WriteMessage, None, None]) -> None:
|
|
102
|
-
for msg in writer:
|
|
103
|
-
if isinstance(msg, message.WriteMigrateTableMessage):
|
|
104
|
-
if msg.table.name not in self._db:
|
|
105
|
-
self._db[msg.table.name] = msg.table
|
|
106
|
-
self._tables[msg.table.name] = msg.table
|
|
107
|
-
elif isinstance(msg, message.WriteInsertMessage):
|
|
108
|
-
table = schema.Table.from_arrow_schema(msg.record.schema)
|
|
109
|
-
self._db[table.name] = msg.record
|
|
110
|
-
else:
|
|
111
|
-
raise NotImplementedError(f"Unknown message type {type(msg)}")
|
|
112
|
-
|
|
113
|
-
def read(self, table: Table) -> Generator[message.ReadMessage, None, None]:
|
|
114
|
-
for table, record in self._db.items():
|
|
115
|
-
yield message.ReadMessage(record)
|
|
116
|
-
|
|
117
|
-
def close(self) -> None:
|
|
118
|
-
self._db = {}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/internal/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/message/read.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/message/write.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/plugin/__init__.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/plugin/plugin.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/__init__.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/binary.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/date32.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/date64.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/float.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/scalar.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/string.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/timestamp.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scalar/vector.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/scheduler/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/schema/__init__.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/schema/arrow.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/schema/column.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/schema/resource.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/schema/table.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/serve/__init__.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/serve/plugin.py
RENAMED
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/stateclient/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/transformers/openapi.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudquery_plugin_sdk-0.1.46 → cloudquery_plugin_sdk-0.1.48}/cloudquery/sdk/types/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|