Skip to content

Commit ed330fb

Browse files
Merge branch 'dev' into fix/simulation-numpy-tests
2 parents dc93fd9 + 3975bbd commit ed330fb

4 files changed

Lines changed: 118 additions & 27 deletions

File tree

concore.py

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -156,26 +156,50 @@ def safe_literal_eval(filename, defaultValue):
156156
# ===================================================================
157157
# Parameter Parsing
158158
# ===================================================================
159+
def parse_params(sparams: str) -> dict:
160+
params = {}
161+
if not sparams:
162+
return params
163+
164+
s = sparams.strip()
165+
166+
#full dict literal
167+
if s.startswith("{") and s.endswith("}"):
168+
try:
169+
val = literal_eval(s)
170+
if isinstance(val, dict):
171+
return val
172+
except (ValueError, SyntaxError):
173+
pass
174+
175+
for item in s.split(";"):
176+
if "=" in item:
177+
key, value = item.split("=", 1) # split only once
178+
key=key.strip()
179+
value=value.strip()
180+
#try to convert to python type (int, float, list, etc.)
181+
# Use literal_eval to preserve backward compatibility (integers/lists)
182+
# Fallback to string for unquoted values (paths, URLs)
183+
try:
184+
params[key] = literal_eval(value)
185+
except (ValueError, SyntaxError):
186+
params[key] = value
187+
return params
188+
159189
try:
160190
sparams_path = concore_params_file
161191
if os.path.exists(sparams_path):
162192
with open(sparams_path, "r") as f:
163-
sparams = f.read()
193+
sparams = f.read().strip()
164194
if sparams: # Ensure sparams is not empty
165195
# Windows sometimes keeps quotes
166196
if sparams[0] == '"' and sparams[-1] == '"': #windows keeps "" need to remove
167197
sparams = sparams[1:-1]
168198

169-
# Convert key=value;key2=value2 to Python dict format
170-
if sparams != '{' and not (sparams.startswith('{') and sparams.endswith('}')): # Check if it needs conversion
171-
logging.debug("converting sparams: "+sparams)
172-
sparams = "{'"+re.sub(';',",'",re.sub('=',"':",re.sub(' ','',sparams)))+"}"
173-
logging.debug("converted sparams: " + sparams)
174-
try:
175-
params = literal_eval(sparams)
176-
except Exception as e:
177-
logging.warning(f"bad params content: {sparams}, error: {e}")
178-
params = dict()
199+
# Parse params using clean function instead of regex
200+
logging.debug("parsing sparams: "+sparams)
201+
params = parse_params(sparams)
202+
logging.debug("parsed params: " + str(params))
179203
else:
180204
params = dict()
181205
else:

concoredocker.py

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,53 @@ def safe_literal_eval(filename, defaultValue):
2525
concore_maxtime_file = os.path.join(inpath, "1", "concore.maxtime")
2626

2727
#9/21/22
28+
def parse_params(sparams):
29+
params = {}
30+
if not sparams:
31+
return params
32+
33+
s = sparams.strip()
34+
35+
# full dict literal
36+
if s.startswith("{") and s.endswith("}"):
37+
try:
38+
val = literal_eval(s)
39+
if isinstance(val, dict):
40+
return val
41+
except (ValueError, SyntaxError):
42+
pass
43+
44+
# keep backward compatibility: comma-separated params
45+
for item in s.split(","):
46+
if "=" in item:
47+
key, value = item.split("=", 1)
48+
key = key.strip()
49+
value = value.strip()
50+
#try to convert to python type (int, float, list, etc.)
51+
# Use literal_eval to preserve backward compatibility (integers/lists)
52+
# Fallback to string for unquoted values (paths, URLs)
53+
try:
54+
params[key] = literal_eval(value)
55+
except (ValueError, SyntaxError):
56+
params[key] = value
57+
return params
58+
2859
try:
29-
sparams = open(concore_params_file).read()
30-
if sparams[0] == '"': #windows keeps "" need to remove
60+
with open(concore_params_file, "r") as f:
61+
sparams = f.read().strip()
62+
63+
if sparams and sparams[0] == '"': # windows keeps quotes
3164
sparams = sparams[1:]
32-
sparams = sparams[0:sparams.find('"')]
33-
if sparams != '{':
34-
print("converting sparams: "+sparams)
35-
sparams = "{'"+re.sub(',',",'",re.sub('=',"':",re.sub(' ','',sparams)))+"}"
36-
print("converted sparams: " + sparams)
37-
try:
38-
params = literal_eval(sparams)
39-
except:
40-
print("bad params: "+sparams)
41-
except:
65+
if '"' in sparams:
66+
sparams = sparams[:sparams.find('"')]
67+
68+
if sparams:
69+
print("parsing sparams:", sparams)
70+
params = parse_params(sparams)
71+
else:
72+
params = dict()
73+
except Exception as e:
74+
print(f"Error reading concore.params: {e}")
4275
params = dict()
4376

4477
#9/30/22

contribute.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
import os,sys,platform,base64,time
44

55
# Intializing the Variables
6-
# Hashed token
7-
BOT_TOKEN = "Z2l0aHViX3BhdF8xMUFYS0pGVFkwU2VhNW9ORjRyN0E5X053WDAwTVBUUU5RVUNTa2lNNlFYZHJET1lZa3B4cTIxS091YVhkeVhUYmRQMzdVUkZaRWpFMjlRRXM5"
6+
BOT_TOKEN = os.environ.get('CONCORE_BOT_TOKEN', '')
87
BOT_ACCOUNT = 'concore-bot' #bot account name
98
REPO_NAME = 'concore-studies' #study repo name
109
UPSTREAM_ACCOUNT = 'ControlCore-Project' #upstream account name
@@ -113,7 +112,7 @@ def decode_token(encoded_token):
113112
PR_BODY = f"Study Name: {STUDY_NAME}\nAuthor Name: {AUTHOR_NAME}" if PR_BODY == "#" else PR_BODY
114113
DIR_PATH = STUDY_NAME
115114
DIR_PATH = DIR_PATH.replace(" ","_")
116-
g = Github(decode_token(BOT_TOKEN))
115+
g = Github(BOT_TOKEN)
117116
repo = g.get_user(BOT_ACCOUNT).get_repo(REPO_NAME)
118117
upstream_repo = g.get_repo(f'{UPSTREAM_ACCOUNT}/{REPO_NAME}') #controlcore-Project/concore-studies
119118
base_ref = upstream_repo.get_branch(repo.default_branch)

tests/test_concore.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,39 @@ def test_unchanged_returns_false_if_diff(self):
176176
concore.olds = "old"
177177

178178
assert concore.unchanged() is False
179-
assert concore.olds == "new"
179+
assert concore.olds == "new"
180+
class TestParseParams:
181+
182+
def test_simple_key_value_pairs(self):
183+
from concore import parse_params
184+
params = parse_params("a=1;b=2")
185+
assert params == {"a": 1, "b": 2}
186+
187+
def test_preserves_whitespace_in_values(self):
188+
from concore import parse_params
189+
params = parse_params("label = hello world ; x = 5")
190+
assert params["label"] == "hello world"
191+
assert params["x"] == 5
192+
193+
def test_embedded_equals_in_value(self):
194+
from concore import parse_params
195+
params = parse_params("url=https://example.com?a=1&b=2")
196+
assert params["url"] == "https://example.com?a=1&b=2"
197+
198+
def test_numeric_and_list_coercion(self):
199+
from concore import parse_params
200+
params = parse_params("delay=5;coeffs=[1,2,3]")
201+
assert params["delay"] == 5
202+
assert params["coeffs"] == [1, 2, 3]
203+
204+
def test_dict_literal_backward_compatibility(self):
205+
from concore import parse_params
206+
params = parse_params("{'a': 1, 'b': 2}")
207+
assert params == {"a": 1, "b": 2}
208+
209+
def test_windows_quoted_input(self):
210+
from concore import parse_params
211+
s = "\"a=1;b=2\""
212+
s = s[1:-1] # simulate quote stripping before parse_params
213+
params = parse_params(s)
214+
assert params == {"a": 1, "b": 2}

0 commit comments

Comments
 (0)