Skip to content

Commit 201257a

Browse files
authored
Merge branch 'rc4.2.0' into feat-pubmlst-util-retry
2 parents 01b7aa8 + ac2bdb1 commit 201257a

File tree

11 files changed

+623
-337
lines changed

11 files changed

+623
-337
lines changed

.github/workflows/run_tests.yml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,13 @@ env:
99

1010
jobs:
1111
build-linux:
12-
runs-on: ubuntu-20.04
13-
strategy:
14-
max-parallel: 5
15-
12+
runs-on: ubuntu-latest
13+
container:
14+
image: python:3.6-slim
15+
1616
steps:
1717
- uses: actions/checkout@v4
18-
- name: Set up Python 3.6
19-
uses: actions/setup-python@v3
20-
with:
21-
python-version: '3.6.15'
18+
2219
- name: Create conda/mamba environment using micromamba
2320
uses: mamba-org/setup-micromamba@v1
2421
with:

configExample.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
"resistances": "/tmp/MLST/references/resistances",
3434
"_comment": "Download path for NCBI genomes, for alignment usage",
3535
"genomes": "/tmp/MLST/references/genomes",
36-
"_comment": "PubMLST credentials",
37-
"pubmlst_credentials": "/tmp/MLST/credentials"
36+
"_comment": "Credentials",
37+
"credentials": "/tmp/MLST/credentials"
3838
},
3939
"_comment": "Database/Flask configuration",
4040
"database": {
@@ -75,9 +75,13 @@
7575
"username": "limsuser",
7676
"password": "mypassword"
7777
},
78-
"_comment": "PubMLST credentials",
78+
"_comment": "Credentials",
7979
"pubmlst": {
8080
"client_id": "",
8181
"client_secret": ""
82+
},
83+
"pasteur": {
84+
"client_id": "",
85+
"client_secret": ""
8286
}
8387
}

microSALT/__init__.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,9 @@
5252

5353
# Ensure PubMLST configuration is included
5454

55-
app.config["pubmlst"] = preset_config.get("pubmlst", {
56-
"client_id": "",
57-
"client_secret": ""
58-
})
59-
6055
app.config["pubmlst"] = preset_config.get("pubmlst", {"client_id": "", "client_secret": ""})
6156

57+
app.config["pasteur"] = preset_config.get("pasteur", {"client_id": "", "client_secret": ""})
6258

6359
# Add extrapaths to config
6460
preset_config["folders"]["expec"] = os.path.abspath(

microSALT/utils/pubmlst/authentication.py

Lines changed: 111 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -5,116 +5,142 @@
55
from dateutil import parser
66
from rauth import OAuth1Session
77

8-
from microSALT import logger
8+
from microSALT import app, logger
99
from microSALT.utils.pubmlst.exceptions import (
10-
PUBMLSTError,
10+
PubMLSTError,
1111
SessionTokenRequestError,
1212
SessionTokenResponseError,
1313
)
1414
from microSALT.utils.pubmlst.helpers import (
15-
BASE_API,
16-
credentials_path_key,
1715
folders_config,
1816
get_path,
17+
get_service_config,
1918
load_auth_credentials,
20-
pubmlst_session_credentials_file_name,
2119
save_session_token,
2220
)
21+
from microSALT.utils.pubmlst.constants import CREDENTIALS_KEY
2322

2423
session_token_validity = 12 # 12-hour validity
2524
session_expiration_buffer = 60 # 60-second buffer
2625

2726

28-
def get_new_session_token(db: str):
29-
"""Request a new session token using all credentials for a specific database."""
30-
logger.debug(f"Fetching a new session token for database '{db}'...")
27+
class ClientAuthentication:
3128

32-
try:
33-
consumer_key, consumer_secret, access_token, access_secret = load_auth_credentials()
29+
def __init__(self, service: str):
30+
"""Initialize the client with the specified service."""
31+
self.service: str = service
32+
self.service_config: dict = get_service_config(service)
33+
self.base_api: str = self.service_config["base_api"]
3434

35-
url = f"{BASE_API}/db/{db}/oauth/get_session_token"
35+
def get_new_session_token(self, db: str):
36+
"""Request a new session token using all credentials for a specific database."""
3637

37-
session = OAuth1Session(
38-
consumer_key=consumer_key,
39-
consumer_secret=consumer_secret,
40-
access_token=access_token,
41-
access_token_secret=access_secret,
42-
)
38+
try:
39+
consumer_key, consumer_secret, access_token, access_secret = load_auth_credentials(
40+
self.service
41+
)
42+
logger.debug(f"Consumer Key: {consumer_key}")
43+
logger.debug(f"Consumer Secret: {consumer_secret}")
44+
logger.debug(f"Access Token: {access_token}")
45+
logger.debug(f"Access Secret: {access_secret}")
46+
47+
url = f"{self.base_api}/db/{db}/oauth/get_session_token"
4348

44-
response = session.get(url, headers={"User-Agent": "BIGSdb API downloader"})
45-
logger.debug(f"Response Status Code: {response.status_code}")
49+
logger.debug(f"Requesting session token from URL: {url}")
4650

47-
if response.ok:
48-
try:
49-
token_data = response.json()
50-
session_token = token_data.get("oauth_token")
51-
session_secret = token_data.get("oauth_token_secret")
51+
session = OAuth1Session(
52+
consumer_key=consumer_key,
53+
consumer_secret=consumer_secret,
54+
access_token=access_token,
55+
access_token_secret=access_secret,
56+
)
5257

53-
if not session_token or not session_secret:
54-
raise SessionTokenResponseError(
55-
db, "Missing 'oauth_token' or 'oauth_token_secret' in response."
58+
response = session.get(url, headers={"User-Agent": "BIGSdb API downloader"})
59+
logger.debug(f"Response Content: {response.content}")
60+
logger.debug(f"Response Status Code: {response.status_code}")
61+
62+
if response.ok:
63+
try:
64+
token_data = response.json()
65+
session_token = token_data.get("oauth_token")
66+
session_secret = token_data.get("oauth_token_secret")
67+
68+
if not session_token or not session_secret:
69+
raise SessionTokenResponseError(
70+
db, "Missing 'oauth_token' or 'oauth_token_secret' in response."
71+
)
72+
73+
expiration_time = datetime.now() + timedelta(hours=session_token_validity)
74+
75+
save_session_token(
76+
service=self.service,
77+
db=db,
78+
token=session_token,
79+
secret=session_secret,
80+
expiration_date=expiration_time,
5681
)
82+
return session_token, session_secret
83+
84+
except (ValueError, KeyError) as e:
85+
raise SessionTokenResponseError(db, f"Invalid response format: {str(e)}")
86+
else:
87+
raise SessionTokenRequestError(db, response.status_code, response.text)
88+
89+
except PubMLSTError as e:
90+
logger.error(f"Error during token fetching: {e}")
91+
raise
92+
except Exception as e:
93+
logger.error(f"Unexpected error: {e}")
94+
raise PubMLSTError(
95+
f"Unexpected error while fetching session token for database '{db}': {e}"
96+
)
5797

58-
expiration_time = datetime.now() + timedelta(hours=session_token_validity)
98+
def load_session_credentials(
99+
self,
100+
db: str,
101+
):
102+
"""Load session token from file for a specific database."""
103+
try:
104+
credentials_file = os.path.join(
105+
get_path(folders_config, CREDENTIALS_KEY),
106+
self.service_config["session_credentials_file_name"],
107+
)
108+
109+
if not os.path.exists(credentials_file):
110+
logger.debug("Session file does not exist. Fetching a new session token.")
111+
return self.get_new_session_token(db)
112+
113+
with open(credentials_file, "r") as f:
114+
try:
115+
all_sessions = json.load(f)
116+
except json.JSONDecodeError as e:
117+
raise SessionTokenResponseError(db, f"Failed to parse session file: {str(e)}")
118+
119+
db_session_data = all_sessions.get("databases", {}).get(db)
120+
if not db_session_data:
121+
logger.debug(
122+
f"No session token found for database '{db}'. Fetching a new session token."
123+
)
124+
return self.get_new_session_token(db)
125+
126+
expiration = parser.parse(db_session_data.get("expiration", ""))
127+
if datetime.now() < expiration - timedelta(seconds=session_expiration_buffer):
128+
logger.debug(f"Using existing session token for database '{db}'.")
129+
session_token = db_session_data.get("token")
130+
session_secret = db_session_data.get("secret")
59131

60-
save_session_token(db, session_token, session_secret, expiration_time)
61132
return session_token, session_secret
62133

63-
except (ValueError, KeyError) as e:
64-
raise SessionTokenResponseError(db, f"Invalid response format: {str(e)}")
65-
else:
66-
raise SessionTokenRequestError(db, response.status_code, response.text)
67-
68-
except PUBMLSTError as e:
69-
logger.error(f"Error during token fetching: {e}")
70-
raise
71-
except Exception as e:
72-
logger.error(f"Unexpected error: {e}")
73-
raise PUBMLSTError(
74-
f"Unexpected error while fetching session token for database '{db}': {e}"
75-
)
76-
77-
78-
def load_session_credentials(db: str):
79-
"""Load session token from file for a specific database."""
80-
try:
81-
credentials_file = os.path.join(
82-
get_path(folders_config, credentials_path_key), pubmlst_session_credentials_file_name
83-
)
84-
85-
if not os.path.exists(credentials_file):
86-
logger.debug("Session file does not exist. Fetching a new session token.")
87-
return get_new_session_token(db)
88-
89-
with open(credentials_file, "r") as f:
90-
try:
91-
all_sessions = json.load(f)
92-
except json.JSONDecodeError as e:
93-
raise SessionTokenResponseError(db, f"Failed to parse session file: {str(e)}")
94-
95-
db_session_data = all_sessions.get("databases", {}).get(db)
96-
if not db_session_data:
97134
logger.debug(
98-
f"No session token found for database '{db}'. Fetching a new session token."
135+
f"Session token for database '{db}' has expired. Fetching a new session token."
136+
)
137+
return self.get_new_session_token(db)
138+
139+
except PubMLSTError as e:
140+
logger.error(f"PuBMLST-specific error occurred: {e}")
141+
raise
142+
except Exception as e:
143+
logger.error(f"Unexpected error: {e}")
144+
raise PubMLSTError(
145+
f"Unexpected error while loading session token for database '{db}': {e}"
99146
)
100-
return get_new_session_token(db)
101-
102-
expiration = parser.parse(db_session_data.get("expiration", ""))
103-
if datetime.now() < expiration - timedelta(seconds=session_expiration_buffer):
104-
logger.debug(f"Using existing session token for database '{db}'.")
105-
session_token = db_session_data.get("token")
106-
session_secret = db_session_data.get("secret")
107-
108-
return session_token, session_secret
109-
110-
logger.debug(
111-
f"Session token for database '{db}' has expired. Fetching a new session token."
112-
)
113-
return get_new_session_token(db)
114-
115-
except PUBMLSTError as e:
116-
logger.error(f"PUBMLST-specific error occurred: {e}")
117-
raise
118-
except Exception as e:
119-
logger.error(f"Unexpected error: {e}")
120-
raise PUBMLSTError(f"Unexpected error while loading session token for database '{db}': {e}")

0 commit comments

Comments
 (0)