airbyte-cdk 6.38.3.dev4101__py3-none-any.whl → 6.38.5.dev0__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.
@@ -48,9 +48,6 @@ from airbyte_cdk.sources.file_based.exceptions import (
48
48
  FileBasedErrorsCollector,
49
49
  FileBasedSourceError,
50
50
  )
51
- from airbyte_cdk.sources.file_based.file_based_stream_permissions_reader import (
52
- AbstractFileBasedStreamPermissionsReader,
53
- )
54
51
  from airbyte_cdk.sources.file_based.file_based_stream_reader import AbstractFileBasedStreamReader
55
52
  from airbyte_cdk.sources.file_based.file_types import default_parsers
56
53
  from airbyte_cdk.sources.file_based.file_types.file_type_parser import FileTypeParser
@@ -103,10 +100,8 @@ class FileBasedSource(ConcurrentSourceAdapter, ABC):
103
100
  cursor_cls: Type[
104
101
  Union[AbstractConcurrentFileBasedCursor, AbstractFileBasedCursor]
105
102
  ] = FileBasedConcurrentCursor,
106
- stream_permissions_reader: Optional[AbstractFileBasedStreamPermissionsReader] = None,
107
103
  ):
108
104
  self.stream_reader = stream_reader
109
- self.stream_permissions_reader = stream_permissions_reader
110
105
  self.spec_class = spec_class
111
106
  self.config = config
112
107
  self.catalog = catalog
@@ -239,8 +234,6 @@ class FileBasedSource(ConcurrentSourceAdapter, ABC):
239
234
  try:
240
235
  parsed_config = self._get_parsed_config(config)
241
236
  self.stream_reader.config = parsed_config
242
- if self.stream_permissions_reader:
243
- self.stream_permissions_reader.config = parsed_config
244
237
  streams: List[Stream] = []
245
238
  for stream_config in parsed_config.streams:
246
239
  # Like state_manager, `catalog_stream` may be None during `check`
@@ -344,23 +337,9 @@ class FileBasedSource(ConcurrentSourceAdapter, ABC):
344
337
  preserve_directory_structure=preserve_directory_structure(parsed_config),
345
338
  )
346
339
 
347
- def _ensure_permissions_reader_available(self) -> None:
348
- """
349
- Validates that a stream permissions reader is available.
350
- Raises a ValueError if the reader is not provided.
351
- """
352
- if not self.stream_permissions_reader:
353
- raise ValueError(
354
- "Stream permissions reader is required for streams that use permissions transfer mode."
355
- )
356
-
357
340
  def _make_permissions_stream(
358
341
  self, stream_config: FileBasedStreamConfig, cursor: Optional[AbstractFileBasedCursor]
359
342
  ) -> AbstractFileBasedStream:
360
- """
361
- Creates a stream that reads permissions from files.
362
- """
363
- self._ensure_permissions_reader_available()
364
343
  return PermissionsFileBasedStream(
365
344
  config=stream_config,
366
345
  catalog_schema=self.stream_schemas.get(stream_config.name),
@@ -371,7 +350,6 @@ class FileBasedSource(ConcurrentSourceAdapter, ABC):
371
350
  validation_policy=self._validate_and_get_validation_policy(stream_config),
372
351
  errors_collector=self.errors_collector,
373
352
  cursor=cursor,
374
- stream_permissions_reader=self.stream_permissions_reader, # type: ignore
375
353
  )
376
354
 
377
355
  def _make_file_based_stream(
@@ -392,10 +370,9 @@ class FileBasedSource(ConcurrentSourceAdapter, ABC):
392
370
  def _make_identities_stream(
393
371
  self,
394
372
  ) -> Stream:
395
- self._ensure_permissions_reader_available()
396
373
  return FileIdentitiesStream(
397
374
  catalog_schema=self.stream_schemas.get(FileIdentitiesStream.IDENTITIES_STREAM_NAME),
398
- stream_permissions_reader=self.stream_permissions_reader, # type: ignore
375
+ stream_reader=self.stream_reader,
399
376
  discovery_policy=self.discovery_policy,
400
377
  errors_collector=self.errors_collector,
401
378
  )
@@ -184,3 +184,97 @@ class AbstractFileBasedStreamReader(ABC):
184
184
  makedirs(path.dirname(local_file_path), exist_ok=True)
185
185
  absolute_file_path = path.abspath(local_file_path)
186
186
  return [file_relative_path, local_file_path, absolute_file_path]
187
+
188
+ @abstractmethod
189
+ def get_file_acl_permissions(self, file: RemoteFile, logger: logging.Logger) -> Dict[str, Any]:
190
+ """
191
+ This function should return the allow list for a given file, i.e. the list of all identities and their permission levels associated with it
192
+
193
+ e.g.
194
+ def get_file_acl_permissions(self, file: RemoteFile, logger: logging.Logger):
195
+ api_conn = some_api.conn(credentials=SOME_CREDENTIALS)
196
+ result = api_conn.get_file_permissions_info(file.id)
197
+ return MyPermissionsModel(
198
+ id=result["id"],
199
+ access_control_list = result["access_control_list"],
200
+ is_public = result["is_public"],
201
+ ).dict()
202
+ """
203
+ raise NotImplementedError(
204
+ f"{self.__class__.__name__} does not implement get_file_acl_permissions(). To support ACL permissions, implement this method and update file_permissions_schema."
205
+ )
206
+
207
+ @abstractmethod
208
+ def load_identity_groups(self, logger: logging.Logger) -> Iterable[Dict[str, Any]]:
209
+ """
210
+ This function should return the Identities in a determined "space" or "domain" where the file metadata (ACLs) are fetched and ACLs items (Identities) exists.
211
+
212
+ e.g.
213
+ def load_identity_groups(self, logger: logging.Logger) -> Dict[str, Any]:
214
+ api_conn = some_api.conn(credentials=SOME_CREDENTIALS)
215
+ users_api = api_conn.users()
216
+ groups_api = api_conn.groups()
217
+ members_api = self.google_directory_service.members()
218
+ for user in users_api.list():
219
+ yield my_identity_model(id=user.id, name=user.name, email_address=user.email, type="user").dict()
220
+ for group in groups_api.list():
221
+ group_obj = my_identity_model(id=group.id, name=groups.name, email_address=user.email, type="group").dict()
222
+ for member in members_api.list(group=group):
223
+ group_obj.member_email_addresses = group_obj.member_email_addresses or []
224
+ group_obj.member_email_addresses.append(member.email)
225
+ yield group_obj.dict()
226
+ """
227
+ raise NotImplementedError(
228
+ f"{self.__class__.__name__} does not implement load_identity_groups(). To support identities, implement this method and update identities_schema."
229
+ )
230
+
231
+ @property
232
+ @abstractmethod
233
+ def file_permissions_schema(self) -> Dict[str, Any]:
234
+ """
235
+ This function should return the permissions schema for file permissions stream.
236
+
237
+ e.g.
238
+ def file_permissions_schema(self) -> Dict[str, Any]:
239
+ # you can also follow the patter we have for python connectors and have a json file and read from there e.g. schemas/identities.json
240
+ return {
241
+ "type": "object",
242
+ "properties": {
243
+ "id": { "type": "string" },
244
+ "file_path": { "type": "string" },
245
+ "access_control_list": {
246
+ "type": "array",
247
+ "items": { "type": "string" }
248
+ },
249
+ "publicly_accessible": { "type": "boolean" }
250
+ }
251
+ }
252
+ """
253
+ raise NotImplementedError(
254
+ f"{self.__class__.__name__} does not implement file_permissions_schema, please return json schema for your permissions streams."
255
+ )
256
+
257
+ @property
258
+ @abstractmethod
259
+ def identities_schema(self) -> Dict[str, Any]:
260
+ """
261
+ This function should return the identities schema for file identity stream.
262
+
263
+ e.g.
264
+ def identities_schema(self) -> Dict[str, Any]:
265
+ # you can also follow the patter we have for python connectors and have a json file and read from there e.g. schemas/identities.json
266
+ return {
267
+ "type": "object",
268
+ "properties": {
269
+ "id": { "type": "string" },
270
+ "remote_id": { "type": "string" },
271
+ "name": { "type": ["null", "string"] },
272
+ "email_address": { "type": ["null", "string"] },
273
+ "member_email_addresses": { "type": ["null", "array"] },
274
+ "type": { "type": "string" },
275
+ }
276
+ }
277
+ """
278
+ raise NotImplementedError(
279
+ f"{self.__class__.__name__} does not implement identities_schema, please return json schema for your identities stream."
280
+ )
@@ -356,7 +356,10 @@ class DefaultFileBasedStream(AbstractFileBasedStream, IncrementalMixin):
356
356
  if "null" not in v:
357
357
  schema[k] = ["null"] + v
358
358
  elif v != "null":
359
- schema[k] = ["null", v]
359
+ if isinstance(v, (str, list)):
360
+ schema[k] = ["null", v]
361
+ else:
362
+ DefaultFileBasedStream._fill_nulls(v)
360
363
  else:
361
364
  DefaultFileBasedStream._fill_nulls(v)
362
365
  elif isinstance(schema, list):
@@ -8,9 +8,7 @@ from typing import Any, Dict, Iterable, Mapping, MutableMapping, Optional
8
8
  from airbyte_cdk.sources.file_based.config.file_based_stream_config import PrimaryKeyType
9
9
  from airbyte_cdk.sources.file_based.discovery_policy import AbstractDiscoveryPolicy
10
10
  from airbyte_cdk.sources.file_based.exceptions import FileBasedErrorsCollector
11
- from airbyte_cdk.sources.file_based.file_based_stream_permissions_reader import (
12
- AbstractFileBasedStreamPermissionsReader,
13
- )
11
+ from airbyte_cdk.sources.file_based.file_based_stream_reader import AbstractFileBasedStreamReader
14
12
  from airbyte_cdk.sources.streams.core import JsonSchema
15
13
  from airbyte_cdk.sources.streams.permissions.identities_stream import IdentitiesStream
16
14
 
@@ -26,13 +24,13 @@ class FileIdentitiesStream(IdentitiesStream):
26
24
  def __init__(
27
25
  self,
28
26
  catalog_schema: Optional[Mapping[str, Any]],
29
- stream_permissions_reader: AbstractFileBasedStreamPermissionsReader,
27
+ stream_reader: AbstractFileBasedStreamReader,
30
28
  discovery_policy: AbstractDiscoveryPolicy,
31
29
  errors_collector: FileBasedErrorsCollector,
32
30
  ) -> None:
33
31
  super().__init__()
34
32
  self.catalog_schema = catalog_schema
35
- self.stream_permissions_reader = stream_permissions_reader
33
+ self.stream_reader = stream_reader
36
34
  self._discovery_policy = discovery_policy
37
35
  self.errors_collector = errors_collector
38
36
  self._cursor: MutableMapping[str, Any] = {}
@@ -42,8 +40,8 @@ class FileIdentitiesStream(IdentitiesStream):
42
40
  return None
43
41
 
44
42
  def load_identity_groups(self) -> Iterable[Dict[str, Any]]:
45
- return self.stream_permissions_reader.load_identity_groups(logger=self.logger)
43
+ return self.stream_reader.load_identity_groups(logger=self.logger)
46
44
 
47
45
  @cache
48
46
  def get_json_schema(self) -> JsonSchema:
49
- return self.stream_permissions_reader.identities_schema
47
+ return self.stream_reader.identities_schema
@@ -7,9 +7,6 @@ from typing import Any, Dict, Iterable
7
7
 
8
8
  from airbyte_cdk.models import AirbyteLogMessage, AirbyteMessage, Level
9
9
  from airbyte_cdk.models import Type as MessageType
10
- from airbyte_cdk.sources.file_based.file_based_stream_permissions_reader import (
11
- AbstractFileBasedStreamPermissionsReader,
12
- )
13
10
  from airbyte_cdk.sources.file_based.stream import DefaultFileBasedStream
14
11
  from airbyte_cdk.sources.file_based.types import StreamSlice
15
12
  from airbyte_cdk.sources.streams.core import JsonSchema
@@ -29,16 +26,10 @@ class PermissionsFileBasedStream(DefaultFileBasedStream):
29
26
  and schema definition, while this class handles the streaming interface.
30
27
  """
31
28
 
32
- def __init__(
33
- self, stream_permissions_reader: AbstractFileBasedStreamPermissionsReader, **kwargs: Any
34
- ):
35
- super().__init__(**kwargs)
36
- self.stream_permissions_reader = stream_permissions_reader
37
-
38
29
  def _filter_schema_invalid_properties(
39
30
  self, configured_catalog_json_schema: Dict[str, Any]
40
31
  ) -> Dict[str, Any]:
41
- return self.stream_permissions_reader.file_permissions_schema
32
+ return self.stream_reader.file_permissions_schema
42
33
 
43
34
  def read_records_from_slice(self, stream_slice: StreamSlice) -> Iterable[AirbyteMessage]:
44
35
  """
@@ -49,7 +40,7 @@ class PermissionsFileBasedStream(DefaultFileBasedStream):
49
40
  no_permissions = False
50
41
  file_datetime_string = file.last_modified.strftime(self.DATE_TIME_FORMAT)
51
42
  try:
52
- permissions_record = self.stream_permissions_reader.get_file_acl_permissions(
43
+ permissions_record = self.stream_reader.get_file_acl_permissions(
53
44
  file, logger=self.logger
54
45
  )
55
46
  if not permissions_record:
@@ -91,4 +82,4 @@ class PermissionsFileBasedStream(DefaultFileBasedStream):
91
82
  Returns:
92
83
  The file permissions schema that defines the structure of permission records
93
84
  """
94
- return self.stream_permissions_reader.file_permissions_schema
85
+ return self.stream_reader.file_permissions_schema
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 6.38.3.dev4101
3
+ Version: 6.38.5.dev0
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://airbyte.com
6
6
  License: MIT
@@ -214,9 +214,8 @@ airbyte_cdk/sources/file_based/discovery_policy/__init__.py,sha256=gl3ey6mZbyfra
214
214
  airbyte_cdk/sources/file_based/discovery_policy/abstract_discovery_policy.py,sha256=dCfXX529Rd5rtopg4VeEgTPJjFtqjtjzPq6LCw18Wt0,605
215
215
  airbyte_cdk/sources/file_based/discovery_policy/default_discovery_policy.py,sha256=-xujTidtrq6HC00WKbjQh1CZdT5LMuzkp5BLjqDmfTY,1007
216
216
  airbyte_cdk/sources/file_based/exceptions.py,sha256=WP0qkG6fpWoBpOyyicgp5YNE393VWyegq5qSy0v4QtM,7362
217
- airbyte_cdk/sources/file_based/file_based_source.py,sha256=bIsut7ivHcl7YPO9cygDn0to23MRLu1Sym7jSr0Iy9A,20051
218
- airbyte_cdk/sources/file_based/file_based_stream_permissions_reader.py,sha256=Vdllp5TsYxaFFsk8NKb_MS9vnbaCmmjLDJszT4tyY0M,5764
219
- airbyte_cdk/sources/file_based/file_based_stream_reader.py,sha256=0cmppYO3pZlFiJrs5oorF4JXv4ErhOeEMrdLG7P-Gdk,6742
217
+ airbyte_cdk/sources/file_based/file_based_source.py,sha256=JXfwc9KaW7PvjAbm2GJ7Ra3DJnCZH4KaE3WytYvtM1Q,18925
218
+ airbyte_cdk/sources/file_based/file_based_stream_reader.py,sha256=d2UZ3C8M-A591KvBvg8kDpVdpox0rKVlRhVy5bi-auc,11209
220
219
  airbyte_cdk/sources/file_based/file_types/__init__.py,sha256=blCLn0-2LC-ZdgcNyDEhqM2RiUvEjEBh-G4-t32ZtuM,1268
221
220
  airbyte_cdk/sources/file_based/file_types/avro_parser.py,sha256=XNx-JC-sgzH9u3nOJ2M59FxBXvtig8LN6BIkeDOavZA,10858
222
221
  airbyte_cdk/sources/file_based/file_types/csv_parser.py,sha256=QlCXB-ry3np67Q_VerQEPoWDOTcPTB6Go4ydZxY9ae4,20445
@@ -242,9 +241,9 @@ airbyte_cdk/sources/file_based/stream/concurrent/cursor/file_based_final_state_c
242
241
  airbyte_cdk/sources/file_based/stream/cursor/__init__.py,sha256=MhFB5hOo8sjwvCh8gangaymdg3EJWYt_72brFOZt068,191
243
242
  airbyte_cdk/sources/file_based/stream/cursor/abstract_file_based_cursor.py,sha256=om-x3gZFPgWDpi15S9RxZmR36VHnk8sytgN6LlBQhAw,1934
244
243
  airbyte_cdk/sources/file_based/stream/cursor/default_file_based_cursor.py,sha256=VGV7xLyBribuBMVrXtO1xqkWJD86bl7yhXtjnwLMohM,7051
245
- airbyte_cdk/sources/file_based/stream/default_file_based_stream.py,sha256=XLU5cNqQ-5mj243gNzMyXtm_oCtg1ORyoqbCsUo9Dn4,18044
246
- airbyte_cdk/sources/file_based/stream/identities_stream.py,sha256=FZH83Geoy3K3nwUk2VVNJERFcXUTnl-4XljjucUM23s,1893
247
- airbyte_cdk/sources/file_based/stream/permissions_file_based_stream.py,sha256=ke82qgm7snOlQTDx94Lqsc0cDkHWi3OJDTrPxffpFqc,3914
244
+ airbyte_cdk/sources/file_based/stream/default_file_based_stream.py,sha256=jyJLu2BUCYWKqrqD0ZUFxnrD0qybny7KbzKznxjIIpM,18199
245
+ airbyte_cdk/sources/file_based/stream/identities_stream.py,sha256=DwgNU-jDp5vZ_WloQSUzBciDnAFMo8bXPjXpQx5-eko,1790
246
+ airbyte_cdk/sources/file_based/stream/permissions_file_based_stream.py,sha256=i0Jn0zuAPomLa4pHSu9TQ3gAN5xXhNzPTYVwUDiDEyE,3523
248
247
  airbyte_cdk/sources/file_based/types.py,sha256=INxG7OPnkdUP69oYNKMAbwhvV1AGvLRHs1J6pIia2FI,218
249
248
  airbyte_cdk/sources/http_config.py,sha256=OBZeuyFilm6NlDlBhFQvHhTWabEvZww6OHDIlZujIS0,730
250
249
  airbyte_cdk/sources/http_logger.py,sha256=H93kPAujHhPmXNX0JSFG3D-SL6yEFA5PtKot9Hu3TYA,1690
@@ -358,9 +357,9 @@ airbyte_cdk/utils/slice_hasher.py,sha256=EDxgROHDbfG-QKQb59m7h_7crN1tRiawdf5uU7G
358
357
  airbyte_cdk/utils/spec_schema_transformations.py,sha256=-5HTuNsnDBAhj-oLeQXwpTGA0HdcjFOf2zTEMUTTg_Y,816
359
358
  airbyte_cdk/utils/stream_status_utils.py,sha256=ZmBoiy5HVbUEHAMrUONxZvxnvfV9CesmQJLDTAIWnWw,1171
360
359
  airbyte_cdk/utils/traced_exception.py,sha256=C8uIBuCL_E4WnBAOPSxBicD06JAldoN9fGsQDp463OY,6292
361
- airbyte_cdk-6.38.3.dev4101.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
362
- airbyte_cdk-6.38.3.dev4101.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
363
- airbyte_cdk-6.38.3.dev4101.dist-info/METADATA,sha256=gO6mN-JTuoinV4QRS-EVjl8S5YUuV9V_yaCFO1gyDoo,6021
364
- airbyte_cdk-6.38.3.dev4101.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
365
- airbyte_cdk-6.38.3.dev4101.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
366
- airbyte_cdk-6.38.3.dev4101.dist-info/RECORD,,
360
+ airbyte_cdk-6.38.5.dev0.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
361
+ airbyte_cdk-6.38.5.dev0.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
362
+ airbyte_cdk-6.38.5.dev0.dist-info/METADATA,sha256=gwRY6sWvIeoJ_Jmemy4eDMpbZrOJaZtlPDiIygQTn_M,6018
363
+ airbyte_cdk-6.38.5.dev0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
364
+ airbyte_cdk-6.38.5.dev0.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
365
+ airbyte_cdk-6.38.5.dev0.dist-info/RECORD,,
@@ -1,131 +0,0 @@
1
- #
2
- # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
3
- #
4
-
5
- import logging
6
- from abc import ABC, abstractmethod
7
- from typing import Any, Dict, Iterable, Optional
8
-
9
- from airbyte_cdk.sources.file_based import AbstractFileBasedSpec
10
- from airbyte_cdk.sources.file_based.remote_file import RemoteFile
11
-
12
-
13
- class AbstractFileBasedStreamPermissionsReader(ABC):
14
- """
15
- This class is responsible for reading file permissions and Identities from a source.
16
- """
17
-
18
- def __init__(self) -> None:
19
- self._config = None
20
-
21
- @property
22
- def config(self) -> Optional[AbstractFileBasedSpec]:
23
- return self._config
24
-
25
- @config.setter
26
- @abstractmethod
27
- def config(self, value: AbstractFileBasedSpec) -> None:
28
- """
29
- FileBasedSource reads the config from disk and parses it, and once parsed, the source sets the config on its StreamReader.
30
-
31
- Note: FileBasedSource only requires the keys defined in the abstract config, whereas concrete implementations of StreamReader
32
- will require keys that (for example) allow it to authenticate with the 3rd party.
33
-
34
- Therefore, concrete implementations of AbstractFileBasedStreamReader's config setter should assert that `value` is of the correct
35
- config type for that type of StreamReader.
36
- """
37
- ...
38
-
39
- @abstractmethod
40
- def get_file_acl_permissions(self, file: RemoteFile, logger: logging.Logger) -> Dict[str, Any]:
41
- """
42
- This function should return the allow list for a given file, i.e. the list of all identities and their permission levels associated with it
43
-
44
- e.g.
45
- def get_file_acl_permissions(self, file: RemoteFile, logger: logging.Logger):
46
- api_conn = some_api.conn(credentials=SOME_CREDENTIALS)
47
- result = api_conn.get_file_permissions_info(file.id)
48
- return MyPermissionsModel(
49
- id=result["id"],
50
- access_control_list = result["access_control_list"],
51
- is_public = result["is_public"],
52
- ).dict()
53
- """
54
- raise NotImplementedError(
55
- f"{self.__class__.__name__} does not implement get_file_acl_permissions(). To support ACL permissions, implement this method and update file_permissions_schema."
56
- )
57
-
58
- @abstractmethod
59
- def load_identity_groups(self, logger: logging.Logger) -> Iterable[Dict[str, Any]]:
60
- """
61
- This function should return the Identities in a determined "space" or "domain" where the file metadata (ACLs) are fetched and ACLs items (Identities) exists.
62
-
63
- e.g.
64
- def load_identity_groups(self, logger: logging.Logger) -> Dict[str, Any]:
65
- api_conn = some_api.conn(credentials=SOME_CREDENTIALS)
66
- users_api = api_conn.users()
67
- groups_api = api_conn.groups()
68
- members_api = self.google_directory_service.members()
69
- for user in users_api.list():
70
- yield my_identity_model(id=user.id, name=user.name, email_address=user.email, type="user").dict()
71
- for group in groups_api.list():
72
- group_obj = my_identity_model(id=group.id, name=groups.name, email_address=user.email, type="group").dict()
73
- for member in members_api.list(group=group):
74
- group_obj.member_email_addresses = group_obj.member_email_addresses or []
75
- group_obj.member_email_addresses.append(member.email)
76
- yield group_obj.dict()
77
- """
78
- raise NotImplementedError(
79
- f"{self.__class__.__name__} does not implement load_identity_groups(). To support identities, implement this method and update identities_schema."
80
- )
81
-
82
- @property
83
- @abstractmethod
84
- def file_permissions_schema(self) -> Dict[str, Any]:
85
- """
86
- This function should return the permissions schema for file permissions stream.
87
-
88
- e.g.
89
- def file_permissions_schema(self) -> Dict[str, Any]:
90
- # you can also follow the patter we have for python connectors and have a json file and read from there e.g. schemas/identities.json
91
- return {
92
- "type": "object",
93
- "properties": {
94
- "id": { "type": "string" },
95
- "file_path": { "type": "string" },
96
- "access_control_list": {
97
- "type": "array",
98
- "items": { "type": "string" }
99
- },
100
- "publicly_accessible": { "type": "boolean" }
101
- }
102
- }
103
- """
104
- raise NotImplementedError(
105
- f"{self.__class__.__name__} does not implement file_permissions_schema, please return json schema for your permissions streams."
106
- )
107
-
108
- @property
109
- @abstractmethod
110
- def identities_schema(self) -> Dict[str, Any]:
111
- """
112
- This function should return the identities schema for file identity stream.
113
-
114
- e.g.
115
- def identities_schema(self) -> Dict[str, Any]:
116
- # you can also follow the patter we have for python connectors and have a json file and read from there e.g. schemas/identities.json
117
- return {
118
- "type": "object",
119
- "properties": {
120
- "id": { "type": "string" },
121
- "remote_id": { "type": "string" },
122
- "name": { "type": ["null", "string"] },
123
- "email_address": { "type": ["null", "string"] },
124
- "member_email_addresses": { "type": ["null", "array"] },
125
- "type": { "type": "string" },
126
- }
127
- }
128
- """
129
- raise NotImplementedError(
130
- f"{self.__class__.__name__} does not implement identities_schema, please return json schema for your identities stream."
131
- )