Skip to content

Commit db34fa9

Browse files
authored
Merge pull request #27 from glassflow/space-management
add space list and create operation
2 parents 88dc0c0 + 943455a commit db34fa9

File tree

8 files changed

+206
-43
lines changed

8 files changed

+206
-43
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
setuptools.setup(
1010
name="glassflow",
11-
version="2.0.1rc",
11+
version="2.0.2rc",
1212
author="glassflow",
1313
description="GlassFlow Python Client SDK",
1414
url="https://learn.glassflow.dev/docs",

src/glassflow/client.py

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from .models import errors, operations
77
from .models.api import PipelineState
88
from .pipeline import Pipeline
9+
from .space import Space
910

1011

1112
class GlassFlowClient(APIClient):
@@ -21,9 +22,9 @@ class GlassFlowClient(APIClient):
2122
2223
"""
2324

24-
def __init__(
25-
self, personal_access_token: str = None, organization_id: str = None
26-
) -> None:
25+
def __init__(self,
26+
personal_access_token: str = None,
27+
organization_id: str = None) -> None:
2728
"""Create a new GlassFlowClient object
2829
2930
Args:
@@ -50,9 +51,8 @@ def get_pipeline(self, pipeline_id: str) -> Pipeline:
5051
requested operation
5152
ClientError: GlassFlow Client Error
5253
"""
53-
return Pipeline(
54-
personal_access_token=self.personal_access_token, id=pipeline_id
55-
).fetch()
54+
return Pipeline(personal_access_token=self.personal_access_token,
55+
id=pipeline_id).fetch()
5656

5757
def create_pipeline(
5858
self,
@@ -112,11 +112,13 @@ def create_pipeline(
112112
env_vars=env_vars,
113113
state=state,
114114
metadata=metadata,
115+
organization_id=self.organization_id,
115116
personal_access_token=self.personal_access_token,
116117
).create()
117118

118119
def list_pipelines(
119-
self, space_ids: list[str] | None = None
120+
self,
121+
space_ids: list[str] | None = None
120122
) -> operations.ListPipelinesResponse:
121123
"""
122124
Lists all pipelines in the GlassFlow API
@@ -156,3 +158,49 @@ def list_pipelines(
156158
total_amount=res_json["total_amount"],
157159
pipelines=res_json["pipelines"],
158160
)
161+
162+
def list_spaces(self) -> operations.ListSpacesResponse:
163+
request = operations.ListSpacesRequest(
164+
organization_id=self.organization_id,
165+
personal_access_token=self.personal_access_token,
166+
)
167+
try:
168+
res = self._request(
169+
method="GET",
170+
endpoint="/spaces",
171+
request=request,
172+
)
173+
res_json = res.raw_response.json()
174+
except errors.ClientError as e:
175+
if e.status_code == 401:
176+
raise errors.UnauthorizedError(e.raw_response) from e
177+
else:
178+
raise e
179+
180+
return operations.ListSpacesResponse(
181+
content_type=res.content_type,
182+
status_code=res.status_code,
183+
raw_response=res.raw_response,
184+
total_amount=res_json["total_amount"],
185+
spaces=res_json["spaces"],
186+
)
187+
188+
def create_space(
189+
self,
190+
name: str,
191+
) -> operations.CreateSpaceResponse:
192+
"""Creates a new Space
193+
194+
Args:
195+
name: Name of the Space
196+
197+
Returns:
198+
Space: New space
199+
200+
Raises:
201+
UnauthorizedError: User does not have permission to perform
202+
the requested operation
203+
"""
204+
return Space(name=name,
205+
personal_access_token=self.personal_access_token,
206+
organization_id=self.organization_id).create()

src/glassflow/models/api/__init__.py

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
1-
from .api import (
2-
CreatePipeline,
3-
FunctionEnvironments,
4-
GetDetailedSpacePipeline,
5-
PipelineState,
6-
SinkConnector,
7-
SourceConnector,
8-
SpacePipeline,
9-
UpdatePipeline,
10-
)
1+
from .api import (CreatePipeline, FunctionEnvironments,
2+
GetDetailedSpacePipeline, PipelineState, SinkConnector,
3+
SourceConnector, SpacePipeline, UpdatePipeline, SpaceScope,
4+
CreateSpace)
115

126
__all__ = [
13-
"CreatePipeline",
14-
"FunctionEnvironments",
15-
"GetDetailedSpacePipeline",
16-
"PipelineState",
17-
"SinkConnector",
18-
"SourceConnector",
19-
"SpacePipeline",
20-
"UpdatePipeline",
7+
"CreatePipeline", "FunctionEnvironments", "GetDetailedSpacePipeline",
8+
"PipelineState", "SinkConnector", "SourceConnector", "SpacePipeline",
9+
"UpdatePipeline", "SpaceScope", "CreateSpace"
2110
]

src/glassflow/models/operations/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
PublishEventResponse,
3030
PublishEventResponseBody,
3131
)
32+
from .space_crud import (ListSpacesResponse, ListSpacesRequest,
33+
CreateSpaceRequest, CreateSpaceResponse)
3234
from .status_access_token import StatusAccessTokenRequest
3335

3436
__all__ = [
@@ -54,4 +56,8 @@
5456
"PublishEventResponse",
5557
"PublishEventResponseBody",
5658
"StatusAccessTokenRequest",
59+
"ListSpacesResponse",
60+
"ListSpacesRequest",
61+
"CreateSpaceRequest",
62+
"CreateSpaceResponse",
5763
]

src/glassflow/models/operations/pipeline_crud.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import dataclasses
44
from enum import Enum
55

6-
from ..api import CreatePipeline, GetDetailedSpacePipeline, PipelineState, SpacePipeline
6+
from ..api import CreatePipeline, GetDetailedSpacePipeline, PipelineState, SpacePipeline, SpaceScope
77
from .base import BaseManagementRequest, BasePipelineManagementRequest, BaseResponse
88

99

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from __future__ import annotations
2+
3+
import dataclasses
4+
from enum import Enum
5+
6+
from ..api import SpaceScope, CreateSpace
7+
from .base import BaseResponse, BaseManagementRequest
8+
9+
10+
@dataclasses.dataclass
11+
class ListSpacesResponse(BaseResponse):
12+
total_amount: int
13+
spaces: list[SpaceScope]
14+
15+
16+
class Order(str, Enum):
17+
asc = "asc"
18+
desc = "desc"
19+
20+
21+
@dataclasses.dataclass
22+
class ListSpacesRequest(BaseManagementRequest):
23+
page_size: int = 50
24+
page: int = 1
25+
order_by: Order = Order.asc
26+
27+
28+
@dataclasses.dataclass
29+
class CreateSpaceRequest(BaseManagementRequest, CreateSpace):
30+
pass
31+
32+
33+
@dataclasses.dataclass
34+
class CreateSpaceResponse(BaseResponse):
35+
name: str
36+
id: str
37+
created_at: str

src/glassflow/pipeline.py

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77

88
class Pipeline(APIClient):
9+
910
def __init__(
1011
self,
1112
personal_access_token: str,
@@ -93,7 +94,8 @@ def __init__(
9394
elif self.source_kind is None and self.source_config is None:
9495
self.source_connector = None
9596
else:
96-
raise ValueError("Both source_kind and source_config must be provided")
97+
raise ValueError(
98+
"Both source_kind and source_config must be provided")
9799

98100
if self.sink_kind is not None and self.sink_config is not None:
99101
self.sink_connector = api.SinkConnector(
@@ -121,8 +123,7 @@ def fetch(self) -> Pipeline:
121123
"""
122124
if self.id is None:
123125
raise ValueError(
124-
"Pipeline id must be provided in order to fetch it's details"
125-
)
126+
"Pipeline id must be provided in order to fetch it's details")
126127

127128
request = operations.GetPipelineRequest(
128129
pipeline_id=self.id,
@@ -178,11 +179,11 @@ def create(self) -> Pipeline:
178179
metadata=self.metadata,
179180
)
180181
if self.name is None:
181-
raise ValueError("Name must be provided in order to create the pipeline")
182+
raise ValueError(
183+
"Name must be provided in order to create the pipeline")
182184
if self.space_id is None:
183185
raise ValueError(
184-
"Space_id must be provided in order to create the pipeline"
185-
)
186+
"Space_id must be provided in order to create the pipeline")
186187
if self.transformation_code is None and self.transformation_file is None:
187188
raise ValueError(
188189
"Either transformation_code or transformation_file must be provided"
@@ -194,7 +195,9 @@ def create(self) -> Pipeline:
194195
**create_pipeline.__dict__,
195196
)
196197

197-
base_res = self._request(method="POST", endpoint="/pipelines", request=request)
198+
base_res = self._request(method="POST",
199+
endpoint="/pipelines",
200+
request=request)
198201
res = operations.CreatePipelineResponse(
199202
status_code=base_res.status_code,
200203
content_type=base_res.content_type,
@@ -204,7 +207,10 @@ def create(self) -> Pipeline:
204207

205208
self.id = res.id
206209
self.created_at = res.created_at
207-
self.access_tokens.append({"name": "default", "token": res.access_token})
210+
self.access_tokens.append({
211+
"name": "default",
212+
"token": res.access_token
213+
})
208214
return self
209215

210216
def delete(self) -> None:
@@ -250,7 +256,8 @@ def get_access_tokens(self) -> Pipeline:
250256
return self
251257

252258
def get_source(
253-
self, pipeline_access_token_name: str | None = None
259+
self,
260+
pipeline_access_token_name: str | None = None
254261
) -> PipelineDataSource:
255262
"""
256263
Get source client to publish data to the pipeline
@@ -269,8 +276,8 @@ def get_source(
269276
return self._get_data_client("source", pipeline_access_token_name)
270277

271278
def get_sink(
272-
self, pipeline_access_token_name: str | None = None
273-
) -> PipelineDataSink:
279+
self,
280+
pipeline_access_token_name: str | None = None) -> PipelineDataSink:
274281
"""
275282
Get sink client to consume data from the pipeline
276283
@@ -288,7 +295,9 @@ def get_sink(
288295
return self._get_data_client("sink", pipeline_access_token_name)
289296

290297
def _get_data_client(
291-
self, client_type: str, pipeline_access_token_name: str | None = None
298+
self,
299+
client_type: str,
300+
pipeline_access_token_name: str | None = None
292301
) -> PipelineDataSource | PipelineDataSink:
293302
if self.id is None:
294303
raise ValueError("Pipeline id must be provided in the constructor")
@@ -302,8 +311,8 @@ def _get_data_client(
302311
break
303312
else:
304313
raise ValueError(
305-
f"Token with name {pipeline_access_token_name} " f"was not found"
306-
)
314+
f"Token with name {pipeline_access_token_name} "
315+
f"was not found")
307316
else:
308317
token = self.access_tokens[0]["token"]
309318
if client_type == "source":
@@ -321,7 +330,8 @@ def _get_data_client(
321330
return client
322331

323332
def _request(
324-
self, method: str, endpoint: str, request: operations.BaseManagementRequest
333+
self, method: str, endpoint: str,
334+
request: operations.BaseManagementRequest
325335
) -> operations.BaseResponse:
326336
try:
327337
return super()._request(
@@ -331,7 +341,8 @@ def _request(
331341
)
332342
except errors.ClientError as e:
333343
if e.status_code == 404:
334-
raise errors.PipelineNotFoundError(self.id, e.raw_response) from e
344+
raise errors.PipelineNotFoundError(self.id,
345+
e.raw_response) from e
335346
elif e.status_code == 401:
336347
raise errors.UnauthorizedError(e.raw_response) from e
337348
else:

0 commit comments

Comments
 (0)