1- import getpass
1+ import argparse
2+
3+ # import getpass
24import logging
3- import pprint
5+ import os
6+
7+ # import pprint
8+ import save_and_restore_api
49
5- import httpx
10+ version = save_and_restore_api . __version__
611
712logger = logging .getLogger (__name__ )
813
1116file_name = "auto_settings.sav"
1217
1318
14- class SaveRestoreAPI :
15- def __init__ (self , * , base_url , timeout ):
16- self ._base_url = base_url
17- self ._timeout = timeout
18- self ._client = None
19- self ._root_node_uid = "44bef5de-e8e6-4014-af37-b8f6c8a939a2"
20-
21- self ._username = None
22- self ._password = None
23- # self._username = "dgavrilov"
24- # self._password = "zelenyi.gena.krokodil"
25-
26- @property
27- def ROOT_NODE_UID (self ):
28- return self ._root_node_uid
29-
30- def open (self ):
31- auth = httpx .BasicAuth (username = self ._username , password = self ._password )
32- self ._client = httpx .Client (base_url = self ._base_url , timeout = timeout , auth = auth )
33-
34- def close (self ):
35- self ._client .close ()
36- self ._client = None
37-
38- def set_username_password (self , username = None , password = None ):
39- if not isinstance (username , str ):
40- print ("Username: " , end = "" )
41- username = input ()
42- if not isinstance (password , str ):
43- password = getpass .getpass ()
44-
45- self ._username = username
46- self ._password = password
47-
48- def login (self , * , username = None , password = None ):
49- params = {"username" : self ._username , "password" : self ._password }
50- self .send_request ("POST" , "/login" , json = params )
51-
52- def send_request (self , method , url , ** kwargs ):
53- response = self ._client .request (method , url , ** kwargs )
54-
55- print (f"{ response .request .url = } " )
56- print (f"{ response .headers .get ('content-type' )= } " )
57-
58- if response .status_code != 200 :
59- print (f"Request failed: status code { response .status_code } " )
60- print (f"Error message: { response .text } " )
61- raise Exception (f"Request failed with code { response .status_code } " )
62-
63- if response .headers .get ("content-type" ) == "application/json" :
64- data = response .json ()
65- else :
66- data = {}
67-
68- return data
69-
70- def get_node (self , node_uid ):
71- return self .send_request ("GET" , f"/node/{ node_uid } " )
72-
73- def get_children (self , node_uid ):
74- return self .send_request ("GET" , f"/node/{ node_uid } /children" )
75-
76- def create_config (self , parent_node_uid , name , pv_list ):
77- config_dict = {
78- "configurationNode" : {
79- "name" : name ,
80- "nodeType" : "CONFIGURATION" ,
81- "userName" : self ._username ,
82- },
83- "configurationData" : {
84- "pvList" : pv_list ,
85- },
86- }
87- print (f"config_dict=\n { pprint .pformat (config_dict )} " )
88- return self .send_request ("PUT" , f"/config?parentNodeId={ parent_node_uid } " , json = config_dict )
89-
90- def update_config (self , node_uid , name , pv_list ):
91- config_dict = {
92- "configurationNode" : {
93- "name" : name ,
94- "nodeType" : "CONFIGURATION" ,
95- "userName" : self ._username ,
96- "uniqueId" : node_uid ,
97- },
98- "configurationData" : {
99- "pvList" : pv_list ,
100- },
101- }
102- print (f"config_dict=\n { pprint .pformat (config_dict )} " )
103- # return self.send_request("POST", f"/config/{node_uid}", json=config_dict)
104- return self .send_request ("POST" , "/config" , json = config_dict )
105-
106-
10719def add_to_pv_list (pv_list , * , pv_name ):
10820 pv_list .append ({"pvName" : pv_name })
10921
@@ -121,34 +33,114 @@ def load_pvs_from_autosave_file(file_name):
12133 return pv_names
12234
12335
36+ def split_config_name (config_name ):
37+ if not config_name .startswith ("/" ):
38+ config_name = "/" + config_name
39+ _ = config_name .split ("/" )
40+ folders , name = _ [1 :- 1 ], _ [- 1 ]
41+ return folders , name
42+
43+
12444def main ():
12545 logging .basicConfig (level = logging .WARNING )
126- # logging.getLogger("bluesky_queueserver").setLevel("INFO")
46+ logging .getLogger ("save-and-restore-api" ).setLevel ("INFO" )
47+
48+ def formatter (prog ):
49+ # Set maximum width such that printed help mostly fits in the RTD theme code block (documentation).
50+ return argparse .RawDescriptionHelpFormatter (prog , max_help_position = 20 , width = 90 )
51+
52+ parser = argparse .ArgumentParser (
53+ description = "save-and-restore-upload: create configuration based on a batch of PVs.\n "
54+ f"save-and-restore-api version { version } \n \n "
55+ "Read a batch of PVs from a file and creates a configuration in Save and Restore service.\n " ,
56+ formatter_class = formatter ,
57+ )
58+
59+ parser .add_argument (
60+ "--file-name" ,
61+ "-f" ,
62+ dest = "file_name" ,
63+ type = str ,
64+ default = None ,
65+ help = "File name with PV names." ,
66+ )
67+
68+ parser .add_argument (
69+ "--config-name" ,
70+ "-c" ,
71+ dest = "config_name" ,
72+ type = str ,
73+ default = None ,
74+ help = "Configuration name including folders, e.g. /detectors/imaging/eiger_config" ,
75+ )
76+
77+ parser .add_argument (
78+ "--create-folders" ,
79+ dest = "create_folders" ,
80+ action = "store_true" ,
81+ help = "Configuration name including folders, e.g. /detectors/imaging/eiger_config" ,
82+ )
83+
84+ parser .add_argument (
85+ "--update" ,
86+ dest = "config_update" ,
87+ action = "store_true" ,
88+ help = "Configuration name including folders, e.g. /detectors/imaging/eiger_config" ,
89+ )
90+
91+ args = parser .parse_args ()
92+ file_name = args .file_name
93+ config_name = args .config_name
94+ create_folders = args .create_folders
95+ config_update = args .config_update
12796
128- SR = SaveRestoreAPI (base_url = BASE_URL , timeout = timeout )
12997 try :
130- pv_names = load_pvs_from_autosave_file (file_name )
131-
132- SR .set_username_password ()
133- SR .open ()
134- SR .login ()
135-
136- data = SR .get_node (SR .ROOT_NODE_UID )
137- print (f"data=\n { pprint .pformat (data )} " )
138- data = SR .get_children (data ["uniqueId" ])
139- print (f"data=\n { pprint .pformat (data )} " )
140- parent_node_uid = data [0 ]["uniqueId" ]
141- name = "test5"
142- pv_list = []
143- for pv_name in pv_names :
144- add_to_pv_list (pv_list , pv_name = pv_name )
145- add_to_pv_list (pv_list , pv_name = "13SIM1:{SimDetector-Cam:1}cam1:BinX" )
146- add_to_pv_list (pv_list , pv_name = "13SIM1:{SimDetector-Cam:1}cam1:BinY" )
147- data = SR .create_config (parent_node_uid , name , pv_list )
148- print (f"data=\n { pprint .pformat (data )} " )
149- node_uid = data ["configurationNode" ]["uniqueId" ]
150- data = SR .update_config (node_uid , name + "a" , pv_list )
151- print (f"data=\n { pprint .pformat (data )} " )
152-
153- finally :
154- SR .close ()
98+ if args .file_name is None :
99+ raise ValueError ("Required '--file-name' ('-f') parameter is not specified" )
100+
101+ if args .config_name is None :
102+ raise ValueError ("Required '--config-name' ('-c') parameter is not specified" )
103+
104+ file_name = os .path .abspath (os .path .expanduser (file_name ))
105+
106+ print (f"file_name={ file_name } " )
107+ print (f"config_name={ config_name } " )
108+ print (f"create_folders={ create_folders } " )
109+ print (f"update={ config_update } " )
110+
111+ if not os .path .isfile (file_name ):
112+ raise ValueError (f"Input file '{ file_name } ' does not exist" )
113+
114+ folders , name = split_config_name (config_name )
115+ print (f"folders={ folders } , name={ name } " )
116+
117+ except Exception as ex :
118+ logger .error (f"Failed: { ex } " )
119+
120+ # SR = SaveRestoreAPI(base_url=BASE_URL, timeout=timeout)
121+ # try:
122+ # pv_names = load_pvs_from_autosave_file(file_name)
123+
124+ # SR.set_username_password()
125+ # SR.open()
126+ # SR.login()
127+
128+ # data = SR.get_node(SR.ROOT_NODE_UID)
129+ # print(f"data=\n{pprint.pformat(data)}")
130+ # data = SR.get_children(data["uniqueId"])
131+ # print(f"data=\n{pprint.pformat(data)}")
132+ # parent_node_uid = data[0]["uniqueId"]
133+ # name = "test5"
134+ # pv_list = []
135+ # for pv_name in pv_names:
136+ # add_to_pv_list(pv_list, pv_name=pv_name)
137+ # add_to_pv_list(pv_list, pv_name="13SIM1:{SimDetector-Cam:1}cam1:BinX")
138+ # add_to_pv_list(pv_list, pv_name="13SIM1:{SimDetector-Cam:1}cam1:BinY")
139+ # data = SR.create_config(parent_node_uid, name, pv_list)
140+ # print(f"data=\n{pprint.pformat(data)}")
141+ # node_uid = data["configurationNode"]["uniqueId"]
142+ # data = SR.update_config(node_uid, name + "a", pv_list)
143+ # print(f"data=\n{pprint.pformat(data)}")
144+
145+ # finally:
146+ # SR.close()
0 commit comments