52
52
53
53
54
54
class Api :
55
- def __init__ (self , server_name : str = None ) -> None :
55
+ def __init__ (self , server_name : str = None , user : str = None , password : str = None , token : str = None ) -> None :
56
56
self .server_name = server_name
57
+ if server_name not in server_configs :
58
+ raise ValueError (f"Server name '{ server_name } ' is not in server_configs" )
59
+
57
60
config = server_configs [server_name ]
58
61
self .app_name : str = config ["app_name" ]
59
62
self .query_name : str = config ["query_name" ]
60
63
self .base_url : str = config ["base_url" ]
61
- self .user = getattr (settings , f"{ server_name } _USER" .upper (), None )
62
- self .password = getattr (settings , f"{ server_name } _PASSWORD" .upper (), None )
63
- self .token = getattr (settings , f"{ server_name } _TOKEN" .upper (), None )
64
+ self .dev_servers = ["xli" , "lrm_dev" , "lrm_qa" ]
65
+
66
+ # Store provided values only
67
+ self ._provided_user = user
68
+ self ._provided_password = password
69
+ self ._provided_token = token
70
+
71
+ def _get_user (self ) -> str | None :
72
+ """Retrieve the user, using the provided value or defaulting to Django settings."""
73
+ return self ._provided_user or getattr (settings , f"{ self .server_name } _USER" .upper (), None )
74
+
75
+ def _get_password (self ) -> str | None :
76
+ """Retrieve the password, using the provided value or defaulting to Django settings."""
77
+ return self ._provided_password or getattr (settings , f"{ self .server_name } _PASSWORD" .upper (), None )
78
+
79
+ def _get_token (self ) -> str | None :
80
+ """Retrieve the token, using the provided value or defaulting to Django settings."""
81
+ return self ._provided_token or getattr (settings , f"{ self .server_name } _TOKEN" .upper (), None )
82
+
83
+ def _get_source_name (self ) -> str :
84
+ """by default, the source is /SDE/. However for the various dev servers, the source is tends to be /scrapers/"""
85
+ return "scrapers" if self .server_name in self .dev_servers else "SDE"
64
86
65
87
def process_response (self , url : str , payload : dict [str , Any ]) -> Any :
66
88
response = requests .post (url , headers = {}, json = payload , verify = False )
67
89
68
- if response .status_code == requests .status_codes . codes .ok :
69
- meaningful_response = response .json ()
90
+ if response .status_code == requests .codes .ok :
91
+ return response .json ()
70
92
else :
71
- raise Exception (response .text )
72
-
73
- return meaningful_response
93
+ response .raise_for_status ()
74
94
75
95
def query (self , page : int , collection_config_folder : str = "" ) -> Any :
76
- if self .server_name :
77
- url = f"{ self .base_url } /api/v1/search.query?Password={ self .password } &User={ self .user } "
96
+ url = f"{ self .base_url } /api/v1/search.query"
97
+ if self .server_name in self .dev_servers :
98
+
99
+ user = self ._get_user ()
100
+ password = self ._get_password ()
101
+
102
+ if not user or not password :
103
+ raise ValueError (
104
+ "User and password are required for the query endpoint on the following servers: {self.dev_servers}"
105
+ )
106
+ authentication = f"?Password={ password } &User={ user } "
107
+ url = f"{ url } { authentication } "
78
108
else :
79
109
url = f"{ self .base_url } /api/v1/search.query"
110
+
80
111
payload = {
81
112
"app" : self .app_name ,
82
113
"query" : {
@@ -89,22 +120,19 @@ def query(self, page: int, collection_config_folder: str = "") -> Any:
89
120
}
90
121
91
122
if collection_config_folder :
92
- if self .server_name in ["xli" , "lrm_dev" , "lrm_qa" ]:
93
- payload ["query" ]["advanced" ]["collection" ] = f"/scrapers/{ collection_config_folder } /"
94
- else :
95
- payload ["query" ]["advanced" ]["collection" ] = f"/SDE/{ collection_config_folder } /"
96
-
97
- response = self .process_response (url , payload )
123
+ source = self ._get_source_name ()
124
+ payload ["query" ]["advanced" ]["collection" ] = f"/{ source } /{ collection_config_folder } /"
98
125
99
- return response
126
+ return self . process_response ( url , payload )
100
127
101
128
def sql_query (self , sql : str ) -> Any :
102
129
"""Executes an SQL query on the configured server using token-based authentication."""
103
- if not self .token :
104
- raise ValueError ("You must have a token to use the SQL endpoint" )
130
+ token = self ._get_token ()
131
+ if not token :
132
+ raise ValueError ("A token is required to use the SQL endpoint" )
105
133
106
134
url = f"{ self .base_url } /api/v1/engine.sql"
107
- headers = {"Content-Type" : "application/json" , "Authorization" : f"Bearer { self . token } " }
135
+ headers = {"Content-Type" : "application/json" , "Authorization" : f"Bearer { token } " }
108
136
payload = json .dumps (
109
137
{
110
138
"method" : "engine.sql" ,
@@ -116,14 +144,15 @@ def sql_query(self, sql: str) -> Any:
116
144
"engines" : "default" ,
117
145
}
118
146
)
147
+
119
148
try :
120
149
response = requests .post (url , headers = headers , data = payload , timeout = 10 )
121
150
response .raise_for_status ()
122
151
return response .json ()
123
152
except requests .exceptions .RequestException as e :
124
- raise Exception (f"API request failed: { str (e )} " )
153
+ raise RuntimeError (f"Api request to SQL endpoint failed: { str (e )} " )
125
154
126
- def get_full_texts (self , collection_config_folder : str ) -> Any :
155
+ def get_full_texts (self , collection_config_folder : str , source : str = None ) -> Any :
127
156
"""
128
157
Retrieves the full texts, URLs, and titles for a specified collection.
129
158
@@ -149,5 +178,9 @@ def get_full_texts(self, collection_config_folder: str) -> Any:
149
178
}
150
179
151
180
"""
152
- sql = f"SELECT url1, text, title FROM sde_index WHERE collection = '/SDE/{ collection_config_folder } /'"
181
+
182
+ if not source :
183
+ source = self ._get_source_name ()
184
+
185
+ sql = f"SELECT url1, text, title FROM sde_index WHERE collection = '/{ source } /{ collection_config_folder } /'"
153
186
return self .sql_query (sql )
0 commit comments