Space Python Loading Python…

Config loader

Write the codeHard 3 stages

The downlink module reads its settings from a JSON file that operators edit by hand. Last week someone typed "256" in quotes, misspelt a key and set twelve retries, and the module started with the wrong settings without a word.

Write the loader that fills in what is missing, checks what is there, and lists every problem before anything starts.

Load settings_text with json.loads(). Start config as a copy of DEFAULTS, fill in what was saved, and print every setting in name order, with the value written as JSON:

downlink_rate_kbps = "256"
log_level = "INFO"
log_levl = "DEBUG"
retries = 12
safe_mode = "yes"
timeout_s = 2.5

dict(DEFAULTS) makes the copy and update() fills it in. json.dumps(value) shows the difference between "256" and 256.

The merged config

Finish stage 1 to unlock this stage.

Check every saved setting, in the order it was saved, and collect a message for each problem: an unknown name, a number setting that is not a number or is outside its range in RANGES, a safe_mode that is not true or false, a log_level that is not in LOG_LEVELS. After the config, print them all, or Config OK:

4 problems:
  downlink_rate_kbps: must be a number, got str
  retries: 12 is outside 0 to 10
  safe_mode: must be true or false, got str
  log_levl: unknown setting

True is also an int in Python, so rule out bool first: isinstance(value, bool) or not isinstance(value, (int, float)).

Four problems

Finish stage 2 to unlock this stage.

Move the work into load_config(text), which returns (config, problems) and never crashes. Text that is not valid JSON is one problem, not valid JSON: and the error's msg; JSON that is not an object, such as a list, is one problem too. In both cases the config is a copy of the defaults. Only settings that pass their check go into the config; the others keep their defaults. Run it on all three texts:

settings_text:
  downlink_rate_kbps: must be a number, got str
  retries: 12 is outside 0 to 10
  safe_mode: must be true or false, got str
  log_levl: unknown setting
good_text:
  Config OK: retries = 5, log_level = WARNING
broken_text:
  not valid JSON: Expecting ',' delimiter
Three files
load_config() for any text
You're not logged in, so your progress is kept in this browser only. Log in to save it, and to use hints and solutions.

Hints

Modifying Dictionaries

modifying-dictionaries.py
# A mission record that changes as the mission goes on
parker = {
    "name": "Parker Solar Probe",
    "launched": 2018,
    "orbits": 20,
    "status": "cruising",
}

# Assign to a key that does not exist yet and it gets added
parker["closest_km"] = 6100000
print(parker)

# The same syntax on an existing key overwrites the old value
parker["status"] = "perihelion pass"
parker["orbits"] = 21
print("Status:", parker["status"], "after", parker["orbits"], "orbits")

# update() applies several changes in one go
parker.update({"speed_kmh": 692000, "status": "record holder"})
print("Speed:", parker["speed_kmh"], "km/h")

# pop() removes a key and hands the value back to you
old_status = parker.pop("status")
print("Removed status was:", old_status)

# del removes a key without giving anything back
del parker["launched"]
print(parker)

# setdefault() only fills in a key that is missing
parker.setdefault("agency", "NASA")
parker.setdefault("name", "Something Else")
print("Name:", parker["name"], "| Agency:", parker["agency"])
Open the full example
script.py
PythonLn 1, Col 1Spaces: 4
Loading the Python environment…

Separate arguments with commas. They're passed on every Run as sys.argv[1:].