35
35
have_collab_token_handler = False
36
36
37
37
38
- __version__ = "0.9.1 "
38
+ __version__ = "0.9.2 "
39
39
40
40
41
41
TOKENFILE = os .path .expanduser ("~/.ebrainstoken" )
@@ -90,7 +90,7 @@ class BaseClient(object):
90
90
91
91
__test__ = False
92
92
93
- def __init__ (self , username = None , password = None , environment = "production" , token = None ):
93
+ def __init__ (self , username = None , password = None , environment = "production" , token = None , interactive = True ):
94
94
self .username = username
95
95
self .verify = True
96
96
self .environment = environment
@@ -118,79 +118,85 @@ def __init__(self, username=None, password=None, environment="production", token
118
118
raise KeyError (f"{ err_msg_base } does not contain environment = { environment } " )
119
119
else :
120
120
raise IOError (f"{ err_msg_base } not found in the current directory." )
121
- if self .token :
122
- pass
123
- elif password is None :
124
- self .token = None
121
+ self ._authenticate (password , interactive )
122
+
123
+ def _authenticate (self , password , interactive ):
124
+ # If a token is provided, we try using it.
125
+ # If not, we try to get a token from the environment
126
+ # or from a local cache
127
+ if not self .token :
125
128
if have_collab_token_handler :
126
129
# if are we running in a Jupyter notebook within the Collaboratory
127
130
# the token is already available
128
131
self .token = oauth .get_token ()
129
132
elif os .path .exists (TOKENFILE ):
130
- if username :
131
- # check for a stored token
133
+ if self .username :
132
134
with open (TOKENFILE ) as fp :
133
- data = json .load (fp ).get (username , None )
135
+ data = json .load (fp ).get (self . username , None )
134
136
if data and "access_token" in data :
135
137
self .token = data ["access_token" ]
136
- if not self ._check_token_valid ():
137
- print (
138
- "EBRAINS authentication token is invalid or has expired. "
139
- "Will need to re-authenticate."
140
- )
141
- self .token = None
142
138
else :
143
- print (f"EBRAINS authentication token file not having required JSON data. data = { data } " )
139
+ print (f"No token for { self . username } found in { TOKENFILE } " )
144
140
else :
145
141
print ("Authentication token file found, but you have not provided your username." )
146
142
else :
147
143
print ("EBRAINS authentication token file not found locally." )
148
144
149
- if self .token is None :
150
- if not username :
151
- print ("\n ==============================================" )
152
- print ("Please enter your EBRAINS username." )
153
- username = input ("EBRAINS Username: " )
154
-
155
- password = os .environ .get ("EBRAINS_PASS" )
156
- if password is not None :
157
- try :
158
- self ._ebrains_auth (username , password )
159
- except Exception :
160
- print (
161
- "Authentication Failure. "
162
- "Possibly incorrect EBRAINS password saved in environment variable 'EBRAINS_PASS'."
163
- )
164
- if not hasattr (self , "config" ):
145
+ # If we don't have a token, we try to authenticate with username and password
146
+ if not self ._check_token_valid ():
147
+ print (
148
+ "EBRAINS authentication token is invalid or has expired. "
149
+ "Will need to re-authenticate."
150
+ )
151
+ if (not self .username ) and interactive :
152
+ print ("\n ==============================================" )
153
+ print ("Please enter your EBRAINS username." )
154
+ self .username = input ("EBRAINS Username: " )
155
+
156
+ if self .username :
157
+ password = password or os .environ .get ("EBRAINS_PASS" )
158
+ if (not password ) and interactive :
159
+ # prompt for password
160
+ print ("Please enter your EBRAINS password: " )
161
+ password = getpass .getpass ()
162
+
163
+ if password :
165
164
try :
166
- # prompt for password
167
- print ("Please enter your EBRAINS password: " )
168
- password = getpass .getpass ()
169
- self ._ebrains_auth (username , password )
165
+ self ._ebrains_auth (self .username , password )
170
166
except Exception :
171
167
print ("Authentication Failure! Password entered is possibly incorrect." )
172
168
raise
173
- with open (TOKENFILE , "w" ) as fp :
174
- json .dump ({username : {"access_token" : self .config ["access_token" ]}}, fp )
175
- os .chmod (TOKENFILE , 0o600 )
176
- else :
177
- try :
178
- self ._ebrains_auth (username , password )
179
- except Exception :
180
- print ("Authentication Failure! Password entered is possibly incorrect." )
181
- raise
169
+
170
+ if self .token :
171
+ self .auth = EBRAINSAuth (self .token )
172
+
173
+ # store token in local cache
174
+ if os .path .exists (TOKENFILE ):
175
+ with open (TOKENFILE , "r" ) as fp :
176
+ token_data = json .load (fp )
177
+ else :
178
+ token_data = {}
179
+ token_data [self .username ] = {"access_token" : self .token }
180
+
182
181
with open (TOKENFILE , "w" ) as fp :
183
- json .dump ({username : {"access_token" : self .config ["access_token" ]}}, fp )
182
+ json .dump (token_data , fp )
183
+ fp .write ("\n " )
184
184
os .chmod (TOKENFILE , 0o600 )
185
- self .auth = EBRAINSAuth (self .token )
185
+ else :
186
+ self .auth = None
186
187
187
188
def _check_token_valid (self ):
188
- url = "https://iam.ebrains.eu/auth/realms/hbp/protocol/openid-connect/userinfo"
189
- data = requests .get (url , auth = EBRAINSAuth (self .token ), verify = self .verify )
190
- if data .status_code == 200 :
191
- return True
192
- else :
193
- return False
189
+ if self .token :
190
+ url = "https://iam.ebrains.eu/auth/realms/hbp/protocol/openid-connect/userinfo"
191
+ data = requests .get (url , auth = EBRAINSAuth (self .token ), verify = self .verify )
192
+ if data .status_code == 200 :
193
+ remote_username = data .json ()["preferred_username" ]
194
+ if self .username and self .username != remote_username :
195
+ raise Exception ("Username does not match token" )
196
+ else :
197
+ self .username = remote_username
198
+ return True
199
+ return False
194
200
195
201
def _format_people_name (self , names ):
196
202
# converts a string of people names separated by semi-colons
@@ -447,7 +453,7 @@ class TestLibrary(BaseClient):
447
453
}
448
454
449
455
token : string, optional
450
- You may directly input a valid authenticated token from Collaboratory v1 or v2 .
456
+ You may directly input a valid authenticated EBRAINS access token .
451
457
Note: you should use the `access_token` and NOT `refresh_token`.
452
458
453
459
Examples
@@ -460,8 +466,8 @@ class TestLibrary(BaseClient):
460
466
461
467
__test__ = False
462
468
463
- def __init__ (self , username = None , password = None , environment = "production" , token = None ):
464
- super (TestLibrary , self ).__init__ (username , password , environment , token )
469
+ def __init__ (self , username = None , password = None , environment = "production" , token = None , interactive = True ):
470
+ super (TestLibrary , self ).__init__ (username , password , environment , token , interactive )
465
471
self ._set_app_info ()
466
472
467
473
def _set_app_info (self ):
@@ -1580,8 +1586,13 @@ def register_result(self, test_result, data_store=None, collab_id=None):
1580
1586
files_to_upload .extend (test_result .related_data ["figures" ])
1581
1587
if files_to_upload :
1582
1588
list_dict_files_uploaded = [
1583
- {"download_url" : f ["filepath" ], "size" : f ["filesize" ]}
1584
- for f in data_store .upload_data (files_to_upload )
1589
+ {
1590
+ "download_url" : ftu ["filepath" ],
1591
+ "size" : ftu ["filesize" ],
1592
+ "hash" : ftu ["hash" ],
1593
+ "local_path" : ftu ["local_path" ]
1594
+ }
1595
+ for ftu in data_store .upload_data (files_to_upload )
1585
1596
]
1586
1597
results_storage .extend (list_dict_files_uploaded )
1587
1598
@@ -1729,8 +1740,8 @@ class ModelCatalog(BaseClient):
1729
1740
1730
1741
__test__ = False
1731
1742
1732
- def __init__ (self , username = None , password = None , environment = "production" , token = None ):
1733
- super (ModelCatalog , self ).__init__ (username , password , environment , token )
1743
+ def __init__ (self , username = None , password = None , environment = "production" , token = None , interactive = True ):
1744
+ super (ModelCatalog , self ).__init__ (username , password , environment , token , interactive )
1734
1745
self ._set_app_info ()
1735
1746
1736
1747
def _set_app_info (self ):
@@ -2541,6 +2552,7 @@ def add_model_instance(
2541
2552
hash = "" ,
2542
2553
morphology = "" ,
2543
2554
license = "" ,
2555
+ collab_id = None
2544
2556
):
2545
2557
"""Register a new model instance.
2546
2558
@@ -2569,6 +2581,10 @@ def add_model_instance(
2569
2581
URL(s) to the morphology file(s) employed in this model.
2570
2582
license : string
2571
2583
Indicates the license applicable for this model instance.
2584
+ collab_id : string
2585
+ Specifies the ID of the host collab in the EBRAINS Collaboratory
2586
+ (the model instance would belong to this collab).
2587
+ If not provided, defaults to the collab of the parent model project.
2572
2588
2573
2589
Returns
2574
2590
-------
@@ -2590,6 +2606,7 @@ def add_model_instance(
2590
2606
2591
2607
instance_data = locals ()
2592
2608
instance_data .pop ("self" )
2609
+ instance_data ["project_id" ] = instance_data .pop ("collab_id" )
2593
2610
2594
2611
for key , val in instance_data .items ():
2595
2612
if val == "" :
@@ -2614,7 +2631,7 @@ def add_model_instance(
2614
2631
else :
2615
2632
handle_response_error ("Error in adding model instance" , response )
2616
2633
2617
- def find_model_instance_else_add (self , model_obj ):
2634
+ def find_model_instance_else_add (self , model_obj , collab_id = None ):
2618
2635
"""Find existing model instance; else create a new instance
2619
2636
2620
2637
This checks if the input model object has an associated model instance.
@@ -2624,6 +2641,9 @@ def find_model_instance_else_add(self, model_obj):
2624
2641
----------
2625
2642
model_obj : object
2626
2643
Python object representing a model.
2644
+ collab_id : str
2645
+ In case of adding a new model instance, add it to this collab.
2646
+ If None, add to the same collab as the parent model.
2627
2647
2628
2648
Returns
2629
2649
-------
@@ -2664,6 +2684,7 @@ def find_model_instance_else_add(self, model_obj):
2664
2684
source = getattr (model_obj , "remote_url" , "" ),
2665
2685
version = model_obj .model_version ,
2666
2686
parameters = getattr (model_obj , "parameters" , "" ),
2687
+ collab_id = collab_id or getattr (model_obj , "collab_id" , None )
2667
2688
)
2668
2689
else :
2669
2690
model_instance = self .get_model_instance (instance_id = model_obj .model_instance_uuid )
0 commit comments