26
26
from hopsworks import client , constants , project , version
27
27
from hopsworks .client .exceptions import ProjectException , RestAPIError
28
28
from hopsworks .connection import Connection
29
+ from hopsworks .core import project_api , secret_api
30
+ from hopsworks .decorators import NoHopsworksConnectionError
29
31
30
32
31
33
# Needs to run before import of hsml and hsfs
42
44
_hw_connection = Connection .connection
43
45
44
46
_connected_project = None
47
+ _secrets_api = None
48
+ _project_api = None
45
49
46
50
47
51
def hw_formatwarning (message , category , filename , lineno , line = None ):
@@ -113,6 +117,7 @@ def login(
113
117
if "REST_ENDPOINT" in os .environ :
114
118
_hw_connection = _hw_connection ()
115
119
_connected_project = _hw_connection .get_project ()
120
+ _initialize_module_apis ()
116
121
print ("\n Logged in to project, explore it here " + _connected_project .get_url ())
117
122
return _connected_project
118
123
@@ -140,6 +145,8 @@ def login(
140
145
elif host is None : # Always do a fallback to Serverless Hopsworks if not defined
141
146
host = constants .HOSTS .APP_HOST
142
147
148
+ is_app = host == constants .HOSTS .APP_HOST
149
+
143
150
# If port same as default, get HOPSWORKS_HOST environment variable
144
151
if port == 443 and "HOPSWORKS_PORT" in os .environ :
145
152
port = os .environ ["HOPSWORKS_PORT" ]
@@ -166,23 +173,24 @@ def login(
166
173
"Could not find api key file on path: {}" .format (api_key_file )
167
174
)
168
175
# If user connected to Serverless Hopsworks, and the cached .hw_api_key exists, then use it.
169
- elif os .path .exists (api_key_path ) and host == constants . HOSTS . APP_HOST :
176
+ elif os .path .exists (api_key_path ) and is_app :
170
177
try :
171
178
_hw_connection = _hw_connection (
172
179
host = host , port = port , api_key_file = api_key_path
173
180
)
174
- _connected_project = _prompt_project (_hw_connection , project )
181
+ _connected_project = _prompt_project (_hw_connection , project , is_app )
175
182
print (
176
183
"\n Logged in to project, explore it here "
177
184
+ _connected_project .get_url ()
178
185
)
186
+ _initialize_module_apis ()
179
187
return _connected_project
180
188
except RestAPIError :
181
189
logout ()
182
190
# API Key may be invalid, have the user supply it again
183
191
os .remove (api_key_path )
184
192
185
- if api_key is None and host == constants . HOSTS . APP_HOST :
193
+ if api_key is None and is_app :
186
194
print (
187
195
"Copy your Api Key (first register/login): https://c.app.hopsworks.ai/account/api/generated"
188
196
)
@@ -198,12 +206,19 @@ def login(
198
206
199
207
try :
200
208
_hw_connection = _hw_connection (host = host , port = port , api_key_value = api_key )
201
- _connected_project = _prompt_project (_hw_connection , project )
209
+ _connected_project = _prompt_project (_hw_connection , project , is_app )
202
210
except RestAPIError as e :
203
211
logout ()
204
212
raise e
205
213
206
- print ("\n Logged in to project, explore it here " + _connected_project .get_url ())
214
+ if _connected_project is None :
215
+ print (
216
+ "Could not find any project, use hopsworks.create_project('my_project') to create one"
217
+ )
218
+ else :
219
+ print ("\n Logged in to project, explore it here " + _connected_project .get_url ())
220
+
221
+ _initialize_module_apis ()
207
222
return _connected_project
208
223
209
224
@@ -245,11 +260,14 @@ def _get_cached_api_key_path():
245
260
return api_key_path
246
261
247
262
248
- def _prompt_project (valid_connection , project ):
263
+ def _prompt_project (valid_connection , project , is_app ):
249
264
saas_projects = valid_connection .get_projects ()
250
265
if project is None :
251
266
if len (saas_projects ) == 0 :
252
- raise ProjectException ("Could not find any project" )
267
+ if is_app :
268
+ raise ProjectException ("Could not find any project" )
269
+ else :
270
+ return None
253
271
elif len (saas_projects ) == 1 :
254
272
return saas_projects [0 ]
255
273
else :
@@ -258,7 +276,9 @@ def _prompt_project(valid_connection, project):
258
276
for index in range (len (saas_projects )):
259
277
print ("\t (" + str (index + 1 ) + ") " + saas_projects [index ].name )
260
278
while True :
261
- project_index = input ("\n Enter project to access: " )
279
+ project_index = input (
280
+ "\n Enter number corresponding to the project to use: "
281
+ )
262
282
# Handle invalid input type
263
283
try :
264
284
project_index = int (project_index )
@@ -285,8 +305,110 @@ def _prompt_project(valid_connection, project):
285
305
286
306
287
307
def logout ():
308
+ """Cleans up and closes the connection for the hopsworks, hsfs and hsml libraries."""
288
309
global _hw_connection
289
- if isinstance (_hw_connection , Connection ):
310
+ global _project_api
311
+ global _secrets_api
312
+
313
+ if _is_connection_active ():
290
314
_hw_connection .close ()
315
+
291
316
client .stop ()
317
+ _project_api = None
318
+ _secrets_api = None
292
319
_hw_connection = Connection .connection
320
+
321
+
322
+ def _is_connection_active ():
323
+ global _hw_connection
324
+ return isinstance (_hw_connection , Connection )
325
+
326
+
327
+ def get_current_project () -> project .Project :
328
+ """Get a reference to the current logged in project.
329
+
330
+ Example for creating a new project
331
+
332
+ ```python
333
+
334
+ import hopsworks
335
+
336
+ hopsworks.login()
337
+
338
+ project = hopsworks.get_current_project()
339
+
340
+ ```
341
+
342
+ # Returns
343
+ `Project`. A project handle object to perform operations on.
344
+ """
345
+ global _connected_project
346
+ if _connected_project is None :
347
+ raise ProjectException ("No project is set for this session" )
348
+ return _connected_project
349
+
350
+
351
+ def _initialize_module_apis ():
352
+ global _project_api
353
+ global _secrets_api
354
+ _project_api = project_api .ProjectApi ()
355
+ _secrets_api = secret_api .SecretsApi ()
356
+
357
+
358
+ def create_project (name : str , description : str = None , feature_store_topic : str = None ):
359
+ """Create a new project.
360
+
361
+ Example for creating a new project
362
+
363
+ ```python
364
+
365
+ import hopsworks
366
+
367
+ hopsworks.login()
368
+
369
+ hopsworks.create_project("my_hopsworks_project", description="An example Hopsworks project")
370
+
371
+ ```
372
+ # Arguments
373
+ name: The name of the project.
374
+ description: optional description of the project
375
+ feature_store_topic: optional feature store topic name
376
+
377
+ # Returns
378
+ `Project`. A project handle object to perform operations on.
379
+ """
380
+ global _hw_connection
381
+ global _connected_project
382
+
383
+ if not _is_connection_active ():
384
+ raise NoHopsworksConnectionError ()
385
+
386
+ new_project = _hw_connection ._project_api ._create_project (
387
+ name , description , feature_store_topic
388
+ )
389
+ if _connected_project is None :
390
+ _connected_project = new_project
391
+ print (
392
+ "Setting {} as the current project, a reference can be retrieved by calling hopsworks.get_current_project()" .format (
393
+ _connected_project .name
394
+ )
395
+ )
396
+ return _connected_project
397
+ else :
398
+ print (
399
+ "You are already using the project {}, to access the new project use hopsworks.login(..., project='{}')" .format (
400
+ _connected_project .name , new_project .name
401
+ )
402
+ )
403
+
404
+
405
+ def get_secrets_api ():
406
+ """Get the secrets api.
407
+
408
+ # Returns
409
+ `SecretsApi`: The Secrets Api handle
410
+ """
411
+ global _secrets_api
412
+ if not _is_connection_active ():
413
+ raise NoHopsworksConnectionError ()
414
+ return _secrets_api
0 commit comments