diaspora-event-sdk 0.2.9__py3-none-any.whl → 0.3.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.
@@ -1,6 +1,5 @@
1
- """ Diaspora Event Fabric: Resilience-enabling services for science from HPC to edge.
1
+ """Diaspora Event Fabric: Resilience-enabling services for science from HPC to edge."""
2
2
 
3
- """
4
3
  from diaspora_event_sdk.version import __version__ as _version
5
4
 
6
5
  __author__ = "The Diaspora Event Team"
@@ -1,9 +1,22 @@
1
1
  import os
2
+ from typing import Union
2
3
 
3
4
 
4
- TOKEN_EXCHANGE = "http://3.220.110.101/"
5
+ # TOKEN_EXCHANGE = "http://3.220.110.101/"
5
6
  DIASPORA_RESOURCE_SERVER = "2b9d2f5c-fa32-45b5-875b-b24cd343b917"
6
7
 
7
8
 
8
9
  def _get_envname():
9
10
  return os.getenv("DIASPORA_SDK_ENVIRONMENT", "production")
11
+
12
+
13
+ def get_web_service_url(envname: Union[str, None] = None) -> str:
14
+ env = envname or _get_envname()
15
+ urls = {
16
+ "production": "https://diaspora-web-service.ml22sevubfnks.us-east-1.cs.amazonlightsail.com",
17
+ "dev": "https://diaspora-web-service-dev.ml22sevubfnks.us-east-1.cs.amazonlightsail.com",
18
+ "local": "http://localhost:8000",
19
+ "legacy": "http://3.220.110.101/",
20
+ }
21
+
22
+ return urls.get(env, urls["production"])
@@ -2,6 +2,7 @@
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import base64
5
+
5
6
  # import logging
6
7
  from datetime import datetime, timezone
7
8
  from urllib.parse import parse_qs, urlparse
@@ -11,6 +12,7 @@ from urllib.parse import parse_qs, urlparse
11
12
  # import pkg_resources
12
13
  from .botocore.auth import SigV4QueryAuth
13
14
  from .botocore.awsrequest import AWSRequest
15
+
14
16
  # from botocore.config import Config
15
17
  from .botocore.credentials import Credentials
16
18
 
@@ -25,7 +27,7 @@ LIB_NAME = "aws-msk-iam-sasl-signer-python"
25
27
 
26
28
 
27
29
  def __get_user_agent__():
28
- return (f"{LIB_NAME}/1.0.1")
30
+ return f"{LIB_NAME}/1.0.1"
29
31
 
30
32
 
31
33
  def __get_expiration_time_ms(request):
@@ -37,15 +39,17 @@ def __get_expiration_time_ms(request):
37
39
  # Parse the signed request
38
40
  parsed_url = urlparse(request.url)
39
41
  parsed_ul_params = parse_qs(parsed_url.query)
40
- parsed_signing_time = datetime.strptime(parsed_ul_params['X-Amz-Date'][0],
41
- "%Y%m%dT%H%M%SZ")
42
+ parsed_signing_time = datetime.strptime(
43
+ parsed_ul_params["X-Amz-Date"][0], "%Y%m%dT%H%M%SZ"
44
+ )
42
45
 
43
46
  # Make the datetime object timezone-aware
44
47
  signing_time = parsed_signing_time.replace(tzinfo=timezone.utc)
45
48
 
46
49
  # Convert the Unix timestamp to milliseconds
47
- expiration_timestamp_seconds = int(
48
- signing_time.timestamp()) + DEFAULT_TOKEN_EXPIRY_SECONDS
50
+ expiration_timestamp_seconds = (
51
+ int(signing_time.timestamp()) + DEFAULT_TOKEN_EXPIRY_SECONDS
52
+ )
49
53
 
50
54
  # Get lifetime of token
51
55
  expiration_timestamp_ms = expiration_timestamp_seconds * 1000
@@ -74,8 +78,7 @@ def __construct_auth_token(region, aws_credentials):
74
78
 
75
79
  # Create SigV4 instance
76
80
  sig_v4 = SigV4QueryAuth(
77
- aws_credentials, SIGNING_NAME, region,
78
- expires=DEFAULT_TOKEN_EXPIRY_SECONDS
81
+ aws_credentials, SIGNING_NAME, region, expires=DEFAULT_TOKEN_EXPIRY_SECONDS
79
82
  )
80
83
 
81
84
  # Create request with url and parameters
@@ -110,10 +113,12 @@ def generate_auth_token(region, aws_debug_creds=False):
110
113
 
111
114
  # Load credentials
112
115
  import os
116
+
113
117
  assert os.environ["AWS_ACCESS_KEY_ID"]
114
118
  assert os.environ["AWS_SECRET_ACCESS_KEY"]
115
119
 
116
- aws_credentials = Credentials(os.environ["AWS_ACCESS_KEY_ID"],
117
- os.environ["AWS_SECRET_ACCESS_KEY"])
120
+ aws_credentials = Credentials(
121
+ os.environ["AWS_ACCESS_KEY_ID"], os.environ["AWS_SECRET_ACCESS_KEY"]
122
+ )
118
123
 
119
124
  return __construct_auth_token(region, aws_credentials)
@@ -7,7 +7,7 @@ from diaspora_event_sdk.sdk.login_manager import (
7
7
  requires_login,
8
8
  )
9
9
 
10
- from ._environments import DIASPORA_RESOURCE_SERVER, TOKEN_EXCHANGE
10
+ from ._environments import DIASPORA_RESOURCE_SERVER, get_web_service_url
11
11
 
12
12
 
13
13
  class Client:
@@ -16,6 +16,8 @@ class Client:
16
16
  environment: Optional[str] = None,
17
17
  login_manager: Optional[LoginManagerProtocol] = None,
18
18
  ):
19
+ self.web_service_address = get_web_service_url(environment)
20
+
19
21
  # if a login manager was passed, no login flow is triggered
20
22
  if login_manager is not None:
21
23
  self.login_manager: LoginManagerProtocol = login_manager
@@ -26,7 +28,8 @@ class Client:
26
28
  self.login_manager.ensure_logged_in()
27
29
 
28
30
  self.web_client = self.login_manager.get_web_client(
29
- base_url=TOKEN_EXCHANGE)
31
+ base_url=self.web_service_address
32
+ )
30
33
  self.auth_client = self.login_manager.get_auth_client()
31
34
  self.subject_openid = self.auth_client.oauth2_userinfo()["sub"]
32
35
 
@@ -151,7 +154,9 @@ class Client:
151
154
  """
152
155
  Increases the number of partitions for a given topic to the specified new partition count.
153
156
  """
154
- return self.web_client.update_topic_partitions(self.subject_openid, topic, new_partitions)
157
+ return self.web_client.update_topic_partitions(
158
+ self.subject_openid, topic, new_partitions
159
+ )
155
160
 
156
161
  @requires_login
157
162
  def reset_topic(self, topic):
@@ -165,14 +170,18 @@ class Client:
165
170
  """
166
171
  Authorizes another user to access a registered topic under the invoker's account.
167
172
  """
168
- return self.web_client.grant_user_access(self.subject_openid, topic, user, "grant")
173
+ return self.web_client.grant_user_access(
174
+ self.subject_openid, topic, user, "grant"
175
+ )
169
176
 
170
177
  @requires_login
171
178
  def revoke_user_access(self, topic, user):
172
179
  """
173
180
  Removes access permissions for another user from a registered topic under the invoker's account.
174
181
  """
175
- return self.web_client.grant_user_access(self.subject_openid, topic, user, "revoke")
182
+ return self.web_client.grant_user_access(
183
+ self.subject_openid, topic, user, "revoke"
184
+ )
176
185
 
177
186
  @requires_login
178
187
  def list_topic_users(self, topic):
@@ -191,10 +200,16 @@ class Client:
191
200
  @requires_login
192
201
  def create_trigger(self, topic, function, function_configs, trigger_configs):
193
202
  """
194
- Creates a new trigger under the user's account with specific function and invocation configurations.
203
+ Creates a new trigger under the user's account with specific function and invocation configurations.
195
204
  """
196
205
  return self.web_client.create_trigger(
197
- self.subject_openid, topic, function, "create", function_configs, trigger_configs)
206
+ self.subject_openid,
207
+ topic,
208
+ function,
209
+ "create",
210
+ function_configs,
211
+ trigger_configs,
212
+ )
198
213
 
199
214
  @requires_login
200
215
  def delete_trigger(self, topic, function):
@@ -202,27 +217,28 @@ class Client:
202
217
  Deletes a trigger and related AWS resources, while the associated topic remains unaffected.
203
218
  """
204
219
  return self.web_client.create_trigger(
205
- self.subject_openid, topic, function, "delete", {}, {})
220
+ self.subject_openid, topic, function, "delete", {}, {}
221
+ )
206
222
 
207
223
  @requires_login
208
224
  def update_trigger(self, trigger_uuid, trigger_configs):
209
225
  """
210
226
  Updates invocation configurations of an existing trigger, identified by its unique trigger UUID.
211
227
  """
212
- return self.web_client.update_trigger(self.subject_openid, trigger_uuid, trigger_configs)
228
+ return self.web_client.update_trigger(
229
+ self.subject_openid, trigger_uuid, trigger_configs
230
+ )
213
231
 
214
232
  @requires_login
215
233
  def list_log_streams(self, trigger):
216
234
  """
217
235
  List log streams of a trigger under the user's account
218
236
  """
219
- return self.web_client.list_log_streams(
220
- self.subject_openid, trigger)
237
+ return self.web_client.list_log_streams(self.subject_openid, trigger)
221
238
 
222
239
  @requires_login
223
240
  def get_log_events(self, trigger, stream):
224
241
  """
225
242
  Get events in a particular log stream of a trigger under the user's account
226
243
  """
227
- return self.web_client.get_log_events(
228
- self.subject_openid, trigger, stream)
244
+ return self.web_client.get_log_events(self.subject_openid, trigger, stream)
@@ -17,7 +17,7 @@ try:
17
17
  def token(self):
18
18
  token, _ = generate_auth_token("us-east-1")
19
19
  return token
20
- except Exception as e:
20
+ except Exception:
21
21
  kafka_available = False
22
22
 
23
23
 
@@ -90,7 +90,7 @@ def block_until_ready(max_minutes=5):
90
90
  value={"message": "Synchronous message from Diaspora SDK"},
91
91
  )
92
92
  result["producer_connection_test"] = future.get(timeout=10)
93
- except Exception as e:
93
+ except Exception:
94
94
  pass
95
95
 
96
96
  def consumer_connection_test(result):
@@ -103,7 +103,7 @@ def block_until_ready(max_minutes=5):
103
103
  for msg in consumer:
104
104
  result["consumer_connection_test"] = msg
105
105
  break
106
- except Exception as e:
106
+ except Exception:
107
107
  pass
108
108
 
109
109
  result, retry_count = {}, 0
@@ -4,6 +4,7 @@ Logic for using client identities with the Diaspora SDK
4
4
  The design is based on the Globus CLI client login:
5
5
  https://github.com/globus/globus-cli/blob/main/src/globus_cli/login_manager/client_login.py
6
6
  """
7
+
7
8
  from __future__ import annotations
8
9
 
9
10
  import logging
@@ -3,8 +3,6 @@ import logging
3
3
 
4
4
  import globus_sdk
5
5
 
6
- from .._environments import TOKEN_EXCHANGE
7
-
8
6
  log = logging.getLogger(__name__)
9
7
 
10
8
 
@@ -27,7 +25,7 @@ def requires_login(func):
27
25
  self.login_manager.run_login_flow()
28
26
  # Initiate a new web client with updated authorizer
29
27
  self.web_client = self.login_manager.get_web_client(
30
- base_url=TOKEN_EXCHANGE
28
+ base_url=self.web_service_address
31
29
  )
32
30
  return func(self, *args, **kwargs)
33
31
 
@@ -32,4 +32,4 @@ def do_link_auth_flow(scopes: List[str]):
32
32
  auth_code = input("Enter the resulting Authorization Code here: ").strip()
33
33
 
34
34
  # finish auth flow
35
- return auth_client.oauth2_exchange_code_for_tokens(auth_code)
35
+ return auth_client.oauth2_exchange_code_for_tokens(auth_code)
@@ -16,14 +16,10 @@ else:
16
16
 
17
17
  @runtime_checkable
18
18
  class LoginManagerProtocol(Protocol):
19
- def ensure_logged_in(self) -> None:
20
- ...
19
+ def ensure_logged_in(self) -> None: ...
21
20
 
22
- def logout(self) -> bool:
23
- ...
21
+ def logout(self) -> bool: ...
24
22
 
25
- def get_auth_client(self) -> globus_sdk.AuthClient:
26
- ...
23
+ def get_auth_client(self) -> globus_sdk.AuthClient: ...
27
24
 
28
- def get_web_client(self, *, base_url: str | None = None) -> WebClient:
29
- ...
25
+ def get_web_client(self, *, base_url: str | None = None) -> WebClient: ...
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import json
4
3
  import os
5
4
  import pathlib
6
5
 
@@ -8,7 +7,6 @@ from globus_sdk.tokenstorage import SQLiteAdapter
8
7
 
9
8
  from .._environments import _get_envname
10
9
  from .client_login import get_client_login, is_client_login
11
- from .globus_auth import internal_auth_client
12
10
 
13
11
 
14
12
  def _home() -> pathlib.Path:
@@ -5,7 +5,7 @@ import globus_sdk
5
5
 
6
6
  from diaspora_event_sdk.sdk.utils.uuid_like import UUID_LIKE_T
7
7
 
8
- from ._environments import TOKEN_EXCHANGE
8
+ from ._environments import get_web_service_url
9
9
 
10
10
 
11
11
  class WebClient(globus_sdk.BaseClient):
@@ -18,7 +18,7 @@ class WebClient(globus_sdk.BaseClient):
18
18
  **kwargs,
19
19
  ):
20
20
  if base_url is None:
21
- base_url = TOKEN_EXCHANGE
21
+ base_url = get_web_service_url(environment)
22
22
 
23
23
  super().__init__(environment=environment, base_url=base_url, **kwargs)
24
24
 
@@ -36,15 +36,14 @@ class WebClient(globus_sdk.BaseClient):
36
36
  ) -> globus_sdk.GlobusHTTPResponse:
37
37
  return self.put(
38
38
  f"/api/v2/topic/{topic}",
39
- headers={"Subject": str(subject), "Action": action}
39
+ headers={"Subject": str(subject), "Action": action},
40
40
  )
41
41
 
42
42
  def get_topic_configs(
43
43
  self, subject: UUID_LIKE_T, topic: str
44
44
  ) -> globus_sdk.GlobusHTTPResponse:
45
45
  return self.get(
46
- f"/api/v2/topic/{topic}",
47
- headers={"Subject": str(subject), "Topic": topic}
46
+ f"/api/v2/topic/{topic}", headers={"Subject": str(subject), "Topic": topic}
48
47
  )
49
48
 
50
49
  def update_topic_configs(
@@ -52,9 +51,12 @@ class WebClient(globus_sdk.BaseClient):
52
51
  ) -> globus_sdk.GlobusHTTPResponse:
53
52
  return self.post(
54
53
  f"/api/v2/topic/{topic}",
55
- headers={"Subject": str(subject), "Topic": topic,
56
- "Content-Type": "text/plain"},
57
- data=json.dumps(configs).encode("utf-8")
54
+ headers={
55
+ "Subject": str(subject),
56
+ "Topic": topic,
57
+ "Content-Type": "text/plain",
58
+ },
59
+ data=json.dumps(configs).encode("utf-8"),
58
60
  )
59
61
 
60
62
  def update_topic_partitions(
@@ -62,8 +64,11 @@ class WebClient(globus_sdk.BaseClient):
62
64
  ) -> globus_sdk.GlobusHTTPResponse:
63
65
  return self.post(
64
66
  f"/api/v2/topic/{topic}/partitions",
65
- headers={"Subject": str(subject), "Topic": topic,
66
- "NewPartitions": str(new_partitions)}
67
+ headers={
68
+ "Subject": str(subject),
69
+ "Topic": topic,
70
+ "NewPartitions": str(new_partitions),
71
+ },
67
72
  )
68
73
 
69
74
  def reset_topic(
@@ -71,8 +76,7 @@ class WebClient(globus_sdk.BaseClient):
71
76
  ) -> globus_sdk.GlobusHTTPResponse:
72
77
  return self.post(
73
78
  f"/api/v2/topic/{topic}/reset",
74
- headers={"Subject": str(subject),
75
- "Topic": topic}
79
+ headers={"Subject": str(subject), "Topic": topic},
76
80
  )
77
81
 
78
82
  def grant_user_access(
@@ -80,8 +84,12 @@ class WebClient(globus_sdk.BaseClient):
80
84
  ) -> globus_sdk.GlobusHTTPResponse:
81
85
  return self.post(
82
86
  f"/api/v2/topic/{topic}/user",
83
- headers={"Subject": str(subject), "Action": action,
84
- "Topic": topic, "User": str(user)}
87
+ headers={
88
+ "Subject": str(subject),
89
+ "Action": action,
90
+ "Topic": topic,
91
+ "User": str(user),
92
+ },
85
93
  )
86
94
 
87
95
  def list_topic_users(
@@ -89,24 +97,33 @@ class WebClient(globus_sdk.BaseClient):
89
97
  ) -> globus_sdk.GlobusHTTPResponse:
90
98
  return self.get(
91
99
  f"/api/v2/topic/{topic}/users",
92
- headers={"Subject": str(subject),
93
- "Topic": topic}
100
+ headers={"Subject": str(subject), "Topic": topic},
94
101
  )
95
102
 
96
103
  def list_triggers(self, subject: UUID_LIKE_T) -> globus_sdk.GlobusHTTPResponse:
97
104
  return self.get("/api/v2/triggers", headers={"Subject": str(subject)})
98
105
 
99
106
  def create_trigger(
100
- self, subject: UUID_LIKE_T, topic: str, function: str, action: str,
101
- function_configs: dict, trigger_configs: dict
107
+ self,
108
+ subject: UUID_LIKE_T,
109
+ topic: str,
110
+ function: str,
111
+ action: str,
112
+ function_configs: dict,
113
+ trigger_configs: dict,
102
114
  ) -> globus_sdk.GlobusHTTPResponse:
103
115
  return self.put(
104
116
  "/api/v2/trigger",
105
- headers={"Subject": str(subject), "Topic": topic,
106
- "Trigger": function, "Action": action,
107
- "Content-Type": "text/plain"},
108
- data=json.dumps({"function": function_configs,
109
- "trigger": trigger_configs}).encode("utf-8")
117
+ headers={
118
+ "Subject": str(subject),
119
+ "Topic": topic,
120
+ "Trigger": function,
121
+ "Action": action,
122
+ "Content-Type": "text/plain",
123
+ },
124
+ data=json.dumps(
125
+ {"function": function_configs, "trigger": trigger_configs}
126
+ ).encode("utf-8"),
110
127
  )
111
128
 
112
129
  def update_trigger(
@@ -114,24 +131,25 @@ class WebClient(globus_sdk.BaseClient):
114
131
  ) -> globus_sdk.GlobusHTTPResponse:
115
132
  return self.post(
116
133
  f"/api/v2/triggers/{trigger_uuid}",
117
- headers={"Subject": str(subject), "Trigger_id": str(trigger_uuid),
118
- "Content-Type": "text/plain"},
119
- data=json.dumps(trigger_configs).encode("utf-8")
134
+ headers={
135
+ "Subject": str(subject),
136
+ "Trigger_id": str(trigger_uuid),
137
+ "Content-Type": "text/plain",
138
+ },
139
+ data=json.dumps(trigger_configs).encode("utf-8"),
120
140
  )
121
141
 
122
142
  def list_log_streams(
123
143
  self, subject: UUID_LIKE_T, trigger: str
124
144
  ) -> globus_sdk.GlobusHTTPResponse:
125
145
  return self.get(
126
- f"/api/v2/logs",
127
- headers={"Subject": str(subject), "Trigger": trigger}
146
+ "/api/v2/logs", headers={"Subject": str(subject), "Trigger": trigger}
128
147
  )
129
148
 
130
149
  def get_log_events(
131
150
  self, subject: UUID_LIKE_T, trigger: str, stream: str
132
151
  ) -> globus_sdk.GlobusHTTPResponse:
133
152
  return self.get(
134
- f"/api/v2/log",
135
- headers={"Subject": str(subject), "Trigger": trigger,
136
- "Stream": stream}
153
+ "/api/v2/log",
154
+ headers={"Subject": str(subject), "Trigger": trigger, "Stream": stream},
137
155
  )
@@ -1 +1 @@
1
- __version__ = "0.2.9"
1
+ __version__ = "0.3.1"
@@ -199,4 +199,4 @@
199
199
  distributed under the License is distributed on an "AS IS" BASIS,
200
200
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
201
  See the License for the specific language governing permissions and
202
- limitations under the License.
202
+ limitations under the License.
@@ -0,0 +1,46 @@
1
+ Metadata-Version: 2.1
2
+ Name: diaspora-event-sdk
3
+ Version: 0.3.1
4
+ Summary: SDK of Diaspora Event Fabric: Resilience-enabling services for science from HPC to edge
5
+ Home-page: https://github.com/globus-labs/diaspora-event-sdk
6
+ License: Apache 2.0
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: globus-sdk <4,>=3.20.1
10
+ Provides-Extra: kafka-python
11
+ Requires-Dist: kafka-python ; extra == 'kafka-python'
12
+ Provides-Extra: test
13
+ Requires-Dist: pytest ; extra == 'test'
14
+ Requires-Dist: pytest-cov ; extra == 'test'
15
+ Requires-Dist: coverage ; extra == 'test'
16
+ Requires-Dist: mypy ; extra == 'test'
17
+ Requires-Dist: tox ; extra == 'test'
18
+ Requires-Dist: check-manifest ; extra == 'test'
19
+ Requires-Dist: pre-commit ; extra == 'test'
20
+
21
+ # Diaspora Event Fabric SDK
22
+
23
+ ## Installation Guide
24
+ ### Recommended Method: With `kafka-python`
25
+ To integrate with Diaspora Event Fabric using `KafkaProducer` and `KafkaConsumer`, install the SDK with `kafka-python`:
26
+ ```bash
27
+ pip install "diaspora-event-sdk[kafka-python]"
28
+ ```
29
+
30
+ ### Alternative Installation: Without Kafka Client Library
31
+ For other Kafka client libraries (e.g., `confluent-kafka-python`, `aiokafka`), install the SDK without `kafka-python`:
32
+ ```bash
33
+ pip install diaspora-event-sdk
34
+ ```
35
+ Note: This does not include `KafkaProducer` and `KafkaConsumer` dependencies.
36
+
37
+ ## Using Diaspora Event Fabric SDK
38
+ Check our [Notebook](DiasporaDemo.ipynb) for a quickstart and demonstration.
39
+
40
+ <!-- **Getting Started**: Visit our [QuickStart Guide](docs/quickstart.md) for details on using the SDK with the kafka-python library and instructions for other Kafka clients.
41
+
42
+ **Troubleshooting and Credential Management**: Consult our [TrobleShooting Guide](docs/troubleshooting.md) for solving common issues and tips on managing keys effectively. -->
43
+
44
+ <!-- **Advanced Consumers with Faust**: Explore the [Faust Streaming Guide](docs/faust_weather_app.md) for advanced event streaming with Faust. -->
45
+
46
+ <!-- **Advanced Consumer Functions**: See our [Colab example](https://colab.research.google.com/drive/1tPKfxU2qPsLvNTreF6nKINU62k7pQWxa?usp=sharing) for demonstration. -->
@@ -0,0 +1,34 @@
1
+ diaspora_event_sdk/__init__.py,sha256=x5A69JeA_iNi0i1XK3T2wuSTiOLxRhNdGYN4G39wtFw,455
2
+ diaspora_event_sdk/version.py,sha256=r4xAFihOf72W9TD-lpMi6ntWSTKTP2SlzKP1ytkjRbI,22
3
+ diaspora_event_sdk/sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ diaspora_event_sdk/sdk/_environments.py,sha256=lrdUaBCmlv6kESLi3O9EN6cMGXEylO8zWQX7NQ8OKCQ,684
5
+ diaspora_event_sdk/sdk/aws_iam_msk.py,sha256=VMQpA-20fFWaAzzv9TyBpDK8dcMHS4tijjjsYhTJF74,3892
6
+ diaspora_event_sdk/sdk/client.py,sha256=Mzsd8WDyaAGMkNDDjpzrWMLPwyC6JoeFVYb0YERrBrk,8774
7
+ diaspora_event_sdk/sdk/decorators.py,sha256=Gel8AyhIjbf4-FNintTNcOqvC9hHH_YwbOH257Nfmf0,884
8
+ diaspora_event_sdk/sdk/kafka_client.py,sha256=ZwNf83gahsLVRHert8YeiruioWAoEIOSTSKZOY-A2PY,4271
9
+ diaspora_event_sdk/sdk/web_client.py,sha256=mc6OvYgq8Cl-irjOW5FfhU_1fl1nRF8OKlPPmaQc0zo,4992
10
+ diaspora_event_sdk/sdk/botocore/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ diaspora_event_sdk/sdk/botocore/auth.py,sha256=QXwCNMzM0wAqD64RlFd-K27atRpixti73VKConpb1kk,18699
12
+ diaspora_event_sdk/sdk/botocore/awsrequest.py,sha256=fcR28YxbsCk2ZT1rGtgWxhje-sYt-SxIqixjOWAFLcM,9344
13
+ diaspora_event_sdk/sdk/botocore/compat.py,sha256=5A-15L8yJhJLQaWvx3xvLfyf5-oO_Ejc-lK55aF0TjI,11197
14
+ diaspora_event_sdk/sdk/botocore/credentials.py,sha256=upSYlgIcp8piSFtGay4ryiCMqNJD5fWFq802p0DWIfI,2455
15
+ diaspora_event_sdk/sdk/botocore/exceptions.py,sha256=Wcu505IzZuyxOl4aE3iuXL-ByL6GDebWFrby7nACgqY,2002
16
+ diaspora_event_sdk/sdk/botocore/utils.py,sha256=TCSvM3QmwVFTDWmU55c1FtAZS0zMWjTkyywmaL1qfCk,5370
17
+ diaspora_event_sdk/sdk/login_manager/__init__.py,sha256=yeqVgjeHLMX0WZJu2feJmq-fbeXvSxWghVV81ygfY-w,239
18
+ diaspora_event_sdk/sdk/login_manager/client_login.py,sha256=e8o6Tf40AW61auHNhQ_5HV7-LDEuNxTWcsKHVUfgxsg,1836
19
+ diaspora_event_sdk/sdk/login_manager/decorators.py,sha256=JlCEwoceSMmFy6PLQ5kz5mpkKfitJgCVAA6I4I_k1nw,1013
20
+ diaspora_event_sdk/sdk/login_manager/globus_auth.py,sha256=pbDy67Mdf4SKFf0IlXD3ZFGj4lG-xpzFTD1ygW-0H1k,430
21
+ diaspora_event_sdk/sdk/login_manager/login_flow.py,sha256=NjmDtr9QWCG1SIPt9TL3pxcUgLfz2qzzWVHBBMJWvE0,978
22
+ diaspora_event_sdk/sdk/login_manager/manager.py,sha256=AD3f8rx154oesgkpqG0K-eZsEGjntr08Vgrxr1m6uao,7040
23
+ diaspora_event_sdk/sdk/login_manager/protocol.py,sha256=ipAOUi7GYF5YfU-az1LWUbU_rNXHarDwUkKn6TUyjVY,678
24
+ diaspora_event_sdk/sdk/login_manager/tokenstore.py,sha256=ImncC8EIxoAuGtDiZIwdtUgOD2fWo8oBP22G-fiZ5L4,2036
25
+ diaspora_event_sdk/sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
+ diaspora_event_sdk/sdk/utils/uuid_like.py,sha256=xbxf0YXpDhdii16lwPLWRN21qFekHrNrqODSToMPtCg,470
27
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
+ tests/unit/apis_test.py,sha256=S_6JjHU-YAcz6nITveN5qzkINkWrrgDcIPR8Ik8JNf4,4365
29
+ tests/unit/client_test.py,sha256=sJUtPmnNGnohnP38RQrwcJ4D5j3-g1WFQ6gaKf520AQ,3019
30
+ diaspora_event_sdk-0.3.1.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
31
+ diaspora_event_sdk-0.3.1.dist-info/METADATA,sha256=WolDkvsp9WLY5fn9miVBx8I5cxdHDjRTjozPj3ZT4LE,2101
32
+ diaspora_event_sdk-0.3.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
33
+ diaspora_event_sdk-0.3.1.dist-info/top_level.txt,sha256=OVun-67t3fkLFEIwvJuNINgFFvAc--bClYhXjLhMmvs,25
34
+ diaspora_event_sdk-0.3.1.dist-info/RECORD,,
@@ -0,0 +1,132 @@
1
+ import pytest
2
+ import os
3
+ import logging
4
+ from globus_sdk import ConfidentialAppAuthClient
5
+ from diaspora_event_sdk import Client
6
+ from diaspora_event_sdk.sdk.login_manager import tokenstore
7
+
8
+ # Configure module-level logger
9
+ logging.basicConfig(
10
+ level=logging.INFO,
11
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
12
+ )
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ @pytest.fixture(scope="module")
17
+ def setup():
18
+ client_id = os.environ["DIASPORA_SDK_CLIENT_ID"]
19
+ client_secret = os.environ["DIASPORA_SDK_CLIENT_SECRET"]
20
+ requested_scopes = os.environ["CLIENT_SCOPE"]
21
+
22
+ ca = ConfidentialAppAuthClient(
23
+ client_id=client_id,
24
+ client_secret=client_secret,
25
+ )
26
+ token_response = ca.oauth2_client_credentials_tokens(
27
+ requested_scopes=requested_scopes,
28
+ )
29
+ token = token_response.by_resource_server[client_id]
30
+
31
+ storage = tokenstore.get_token_storage_adapter()
32
+ storage.store(token_response)
33
+ storage.get_by_resource_server()
34
+
35
+ return {
36
+ "client_id": client_id,
37
+ "client_secret": client_secret,
38
+ "requested_scopes": requested_scopes,
39
+ "token_response": token_response,
40
+ "token": token,
41
+ }
42
+
43
+
44
+ @pytest.fixture(scope="module")
45
+ def client():
46
+ return Client()
47
+
48
+
49
+ def test_create_key(setup, client):
50
+ key_response = client.create_key()
51
+ assert isinstance(key_response, dict)
52
+ assert "access_key" in key_response
53
+ assert "secret_key" in key_response
54
+ assert "endpoint" in key_response
55
+
56
+
57
+ def test_register_topic(setup, client):
58
+ topic = "topic" + client.subject_openid[-12:]
59
+ register_response = client.register_topic(topic)
60
+ assert register_response["status"] in ["success", "no-op"]
61
+ assert "message" in register_response
62
+
63
+
64
+ def test_list_topics(setup, client):
65
+ topics = client.list_topics()
66
+ assert topics["status"] == "success"
67
+ assert isinstance(topics["topics"], list)
68
+ assert len(topics["topics"]) > 0
69
+ expected_topics = ["diaspora-cicd"]
70
+ assert set(expected_topics).issubset(set(topics["topics"]))
71
+
72
+
73
+ def test_get_topic_configs(setup, client):
74
+ topic = "topic" + client.subject_openid[-12:]
75
+ client.register_topic(topic)
76
+ configs_response = client.get_topic_configs(topic)
77
+ assert configs_response["status"] == "success"
78
+ assert "configs" in configs_response
79
+ assert isinstance(configs_response["configs"], dict)
80
+
81
+
82
+ def test_update_topic_configs(setup, client):
83
+ topic = "topic" + client.subject_openid[-12:]
84
+ client.register_topic(topic)
85
+ configs = {"min.insync.replicas": 1}
86
+ update_response = client.update_topic_configs(topic, configs)
87
+ assert update_response["status"] == "success"
88
+ assert "before" in update_response
89
+ assert "after" in update_response
90
+ assert isinstance(update_response["before"], dict)
91
+ assert isinstance(update_response["after"], dict)
92
+
93
+
94
+ def test_update_topic_partitions(setup, client):
95
+ topic = "topic" + client.subject_openid[-12:]
96
+ client.register_topic(topic)
97
+ new_partitions = 2
98
+ partitions_response = client.update_topic_partitions(topic, new_partitions)
99
+ assert partitions_response["status"] in ["success", "error"]
100
+ if partitions_response["status"] == "error":
101
+ assert "message" in partitions_response
102
+
103
+
104
+ def test_reset_topic(setup, client):
105
+ topic = "topic" + client.subject_openid[-12:]
106
+ client.register_topic(topic)
107
+ reset_response = client.reset_topic(topic)
108
+ assert reset_response["status"] in ["success", "error"]
109
+ if reset_response["status"] == "error":
110
+ assert "message" in reset_response
111
+
112
+
113
+ def test_user_access_management(setup, client):
114
+ topic = "topic" + client.subject_openid[-12:]
115
+ client.register_topic(topic)
116
+ user_id = "e2a8169b-feef-4d56-8eba-ab12747bee04"
117
+ grant_response = client.grant_user_access(topic, user_id)
118
+ assert grant_response["status"] in ["success", "no-op"]
119
+ assert "message" in grant_response
120
+
121
+ list_users_response = client.list_topic_users(topic)
122
+ assert list_users_response["status"] == "success"
123
+ assert "users" in list_users_response
124
+ assert isinstance(list_users_response["users"], list)
125
+
126
+ revoke_response = client.revoke_user_access(topic, user_id)
127
+ assert revoke_response["status"] in ["success", "no-op"]
128
+ assert "message" in revoke_response
129
+
130
+
131
+ if __name__ == "__main__":
132
+ pytest.main(["-s", "tests/unit/test_apis.py"])
@@ -1,51 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: diaspora-event-sdk
3
- Version: 0.2.9
4
- Summary: SDK of Diaspora Event Fabric: Resilience-enabling services for science from HPC to edge
5
- Home-page: https://github.com/globus-labs/diaspora-event-sdk
6
- License: Apache 2.0
7
- Platform: UNKNOWN
8
- Description-Content-Type: text/markdown
9
- License-File: LICENSE
10
- Requires-Dist: globus-sdk <4,>=3.20.1
11
- Provides-Extra: kafka-python
12
- Requires-Dist: kafka-python ; extra == 'kafka-python'
13
- Provides-Extra: test
14
- Requires-Dist: pytest ; extra == 'test'
15
- Requires-Dist: pytest-cov ; extra == 'test'
16
- Requires-Dist: coverage ; extra == 'test'
17
- Requires-Dist: mypy ; extra == 'test'
18
- Requires-Dist: tox ; extra == 'test'
19
- Requires-Dist: check-manifest ; extra == 'test'
20
-
21
- # Diaspora: Hybrid Event-Driven Architecture for Distributed Scientific Computing
22
-
23
- ## Event Fabric SDK Installation Guide
24
- ### Recommended Method: Use with `kafka-python`
25
- For easy integration with Diaspora Event Fabric, use the `KafkaProducer` and `KafkaConsumer` classes from our SDK. This requires the `kafka-python` library.
26
-
27
- To install the Event Fabric SDK and `kafka-python,` with the following command:
28
- ```bash
29
- pip install "diaspora-event-sdk[kafka-python]"
30
- ```
31
-
32
- ### Alternative Installation: Without Kafka Client Library
33
- To use alternative Kafka client libraries (e.g., `confluent-kafka-python`, `aiokafka`, and libraries for other programming laguages), you can install the SDK without the `kafka-python` dependency. This option still provides topic-level access control (authorization) and login credential management features.
34
-
35
- To install the SDK without `kafka-python`, use:
36
- ```bash
37
- pip install diaspora-event-sdk
38
- ```
39
- Note: This method does not include dependencies for `KafkaProducer` and `KafkaConsumer` classes mentioned in the QuickStart
40
-
41
- ## Use Diaspora Event Fabric SDK
42
-
43
- **Getting Started**: Visit our [QuickStart Guide](docs/quickstart.md) for details on using the SDK with the kafka-python library and instructions for other Kafka clients.
44
-
45
- **Troubleshooting and Credential Management**: Consult our [TrobleShooting Guide](docs/troubleshooting.md) for solving common issues and tips on managing keys effectively.
46
-
47
- **Advanced Consumers with Faust**: Explore the [Faust Streaming Guide](docs/faust_weather_app.md) for advanced event streaming with Faust.
48
-
49
- **Advanced Consumer Functions**: See our [Colab example](https://colab.research.google.com/drive/1tPKfxU2qPsLvNTreF6nKINU62k7pQWxa?usp=sharing) for demonstration.
50
-
51
-
@@ -1,33 +0,0 @@
1
- diaspora_event_sdk/__init__.py,sha256=v8IN3-WFpliakQKru8TAcmQ4IRdvRe_m9-abSDnGIFM,457
2
- diaspora_event_sdk/version.py,sha256=F8OVhAhMXSkvvXYgZtbPn2SG1AQC3joK4yu-FrHt81Y,22
3
- diaspora_event_sdk/sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- diaspora_event_sdk/sdk/_environments.py,sha256=QyQA7dV4goUKUoxAoaes8OGv0xKxz2qiFBHNGr-vQNA,204
5
- diaspora_event_sdk/sdk/aws_iam_msk.py,sha256=rT6RipRVt-Zf7pTsMf9UhH2HDNC0FW28LhciVH_45bc,3942
6
- diaspora_event_sdk/sdk/client.py,sha256=fbjP_YRmGF2eItnMxNkdz5RIRvur0_P8DhE6AlYk4tM,8541
7
- diaspora_event_sdk/sdk/decorators.py,sha256=Gel8AyhIjbf4-FNintTNcOqvC9hHH_YwbOH257Nfmf0,884
8
- diaspora_event_sdk/sdk/kafka_client.py,sha256=xAxuPmMXIv0i_K_PFqc_BEG3wdGsFdYYvd7gUzeoLV8,4286
9
- diaspora_event_sdk/sdk/web_client.py,sha256=Rkp0ZUUXCeqbfVFUqX2oxvuLwqqW5_jsJJNN-v2L4FI,4770
10
- diaspora_event_sdk/sdk/botocore/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- diaspora_event_sdk/sdk/botocore/auth.py,sha256=QXwCNMzM0wAqD64RlFd-K27atRpixti73VKConpb1kk,18699
12
- diaspora_event_sdk/sdk/botocore/awsrequest.py,sha256=fcR28YxbsCk2ZT1rGtgWxhje-sYt-SxIqixjOWAFLcM,9344
13
- diaspora_event_sdk/sdk/botocore/compat.py,sha256=5A-15L8yJhJLQaWvx3xvLfyf5-oO_Ejc-lK55aF0TjI,11197
14
- diaspora_event_sdk/sdk/botocore/credentials.py,sha256=upSYlgIcp8piSFtGay4ryiCMqNJD5fWFq802p0DWIfI,2455
15
- diaspora_event_sdk/sdk/botocore/exceptions.py,sha256=Wcu505IzZuyxOl4aE3iuXL-ByL6GDebWFrby7nACgqY,2002
16
- diaspora_event_sdk/sdk/botocore/utils.py,sha256=TCSvM3QmwVFTDWmU55c1FtAZS0zMWjTkyywmaL1qfCk,5370
17
- diaspora_event_sdk/sdk/login_manager/__init__.py,sha256=yeqVgjeHLMX0WZJu2feJmq-fbeXvSxWghVV81ygfY-w,239
18
- diaspora_event_sdk/sdk/login_manager/client_login.py,sha256=8ild28_cgPSrLtg3Jhmzpg3EymAvH2UdAhKY52oOB_c,1835
19
- diaspora_event_sdk/sdk/login_manager/decorators.py,sha256=EFEp71d0oJ7vo2H8W7DJ2gPrDfGzeNXUNxri1C0l8h0,1047
20
- diaspora_event_sdk/sdk/login_manager/globus_auth.py,sha256=pbDy67Mdf4SKFf0IlXD3ZFGj4lG-xpzFTD1ygW-0H1k,430
21
- diaspora_event_sdk/sdk/login_manager/login_flow.py,sha256=6Vi_e3rACYdv4TRXPAvUv5xivCRkCo4DS841Ixu_r24,977
22
- diaspora_event_sdk/sdk/login_manager/manager.py,sha256=AD3f8rx154oesgkpqG0K-eZsEGjntr08Vgrxr1m6uao,7040
23
- diaspora_event_sdk/sdk/login_manager/protocol.py,sha256=RCuo2jy_XkpZvbxnKlDfTKs-L6b9_8_JR-Kq9wHwhoM,710
24
- diaspora_event_sdk/sdk/login_manager/tokenstore.py,sha256=Kq0IZGf9G9dE44yoyUZInod5xL_8caN9OugeTK6GBGg,2094
25
- diaspora_event_sdk/sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- diaspora_event_sdk/sdk/utils/uuid_like.py,sha256=xbxf0YXpDhdii16lwPLWRN21qFekHrNrqODSToMPtCg,470
27
- tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- tests/unit/test_client.py,sha256=sJUtPmnNGnohnP38RQrwcJ4D5j3-g1WFQ6gaKf520AQ,3019
29
- diaspora_event_sdk-0.2.9.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
30
- diaspora_event_sdk-0.2.9.dist-info/METADATA,sha256=L3RH4LPf5XaJnONbmOfFTK9awU5LT3agzb6KkaBHZQs,2449
31
- diaspora_event_sdk-0.2.9.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
32
- diaspora_event_sdk-0.2.9.dist-info/top_level.txt,sha256=OVun-67t3fkLFEIwvJuNINgFFvAc--bClYhXjLhMmvs,25
33
- diaspora_event_sdk-0.2.9.dist-info/RECORD,,
File without changes