mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-09-24 23:01:18 +08:00
feat(curriculum): add user configuration manager lab (#60845)
Co-authored-by: Dario-DC <105294544+Dario-DC@users.noreply.github.com>
This commit is contained in:
@@ -4257,9 +4257,11 @@
|
||||
"In this workshop, you'll practice working with dictionaries and sets while validating a collection of medical data."
|
||||
]
|
||||
},
|
||||
"lab-placeholder-dictionaries-and-sets": {
|
||||
"title": "Placeholder - waiting for title",
|
||||
"intro": [""]
|
||||
"lab-user-configuration-manager": {
|
||||
"title": "Build a User Configuration Manager",
|
||||
"intro": [
|
||||
"In this lab, you will practice working with dictionaries in Python."
|
||||
]
|
||||
},
|
||||
"review-dictionaries-and-sets": {
|
||||
"title": "Dictionaries and Sets review",
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Introduction to the Build a User Configuration Manager
|
||||
block: lab-user-configuration-manager
|
||||
superBlock: full-stack-developer
|
||||
---
|
||||
|
||||
## Introduction to the Build a User Configuration Manager
|
||||
|
||||
In this lab you will practice dictionaries in Python by building a small app that manages user configuration settings.
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Build a User Configuration Manager",
|
||||
"isUpcomingChange": true,
|
||||
"dashedName": "lab-user-configuration-manager",
|
||||
"superBlock": "full-stack-developer",
|
||||
"challengeOrder": [
|
||||
{
|
||||
"id": "684aaf9ec670c68d20efd0d0",
|
||||
"title": "Build a User Configuration Manager"
|
||||
}
|
||||
],
|
||||
"blockLayout": "link",
|
||||
"blockType": "lab",
|
||||
"helpCategory": "Python"
|
||||
}
|
||||
+457
@@ -0,0 +1,457 @@
|
||||
---
|
||||
id: 684aaf9ec670c68d20efd0d0
|
||||
title: Build a User Configuration Manager
|
||||
challengeType: 27
|
||||
dashedName: build-a-user-configuration-manager
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In this lab, you will build a User Configuration Manager that allows users to manage their settings such as theme, language, and notifications. You will implement functions to add, update, delete, and view user settings.
|
||||
|
||||
**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
|
||||
|
||||
**User Stories:**
|
||||
|
||||
1. You should define a function named `add_setting` with two parameters representing a dictionary of settings and a tuple containing a key-value pair
|
||||
|
||||
1. `add_setting` function should:
|
||||
|
||||
- Convert the key and value to lowercase.
|
||||
- If the key setting exists, return `Setting '[key]' already exists! Cannot add a new setting with this name.`
|
||||
- If the key setting doesn't exist, add the key-value pair to the given dictionary of settings and return `Setting '[key]' added with value '[value]' successfully!`.
|
||||
- The messages returned should have the key and value in lowercase.
|
||||
|
||||
1. You should define a function named `update_setting` with two parameters representing a dictionary of settings and a tuple containing a key-value pair.
|
||||
|
||||
1. `update_setting` function should:
|
||||
|
||||
- Convert the key and value to lowercase.
|
||||
- If the key setting exists, update its value in the given dictionary of settings and return: `Setting '[key]' updated to '[value]' successfully!`
|
||||
- If the key setting doesn't exist, return `Setting '[key]' does not exist! Cannot update a non-existing setting.`
|
||||
- The messages returned should have the key and value in lowercase.
|
||||
|
||||
|
||||
1. You should define a function named `delete_setting` with two parameters representing a dictionary of settings and a key.
|
||||
|
||||
1. `delete_setting` function should:
|
||||
|
||||
- Convert the key passed to lowercase.
|
||||
- If the key setting exists, remove the key-value pair from the given dictionary of settings and return `Setting '[key]' deleted successfully!`
|
||||
- If the key setting does not exist, return `Setting not found!`
|
||||
- The messages returned should have the key in lowercase.
|
||||
|
||||
1. You should define a function named `view_settings` with one parameter representing a dictionary of settings.
|
||||
|
||||
1. `view_settings` function should:
|
||||
|
||||
- Return `No settings available.` if the given dictionary of settings is empty.
|
||||
- If the dictionary contains any settings, return a string displaying the settings. The string should start with `Current User Settings:` followed by the key-value pairs, each on a new line and with the key capitalized. For example, `view_settings({'theme': 'dark', 'notifications': 'enabled', 'volume': 'high'})` should return:
|
||||
|
||||
```md
|
||||
Current User Settings:
|
||||
Theme: dark
|
||||
Notifications: enabled
|
||||
Volume: high
|
||||
|
||||
```
|
||||
|
||||
1. For testing the code, you should create a dictionary named `test_settings` to store some user configuration preferences.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create a dictionary named `test_settings` and add some values to it.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
is_dict = isinstance(test_settings, dict)
|
||||
length = len(test_settings)
|
||||
assert is_dict and length > 0
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
You should define a function named `add_setting`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).has_function("add_setting")`)) })
|
||||
```
|
||||
|
||||
The `add_setting` function should have two parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
import inspect
|
||||
sig = inspect.signature(add_setting)
|
||||
assert len(sig.parameters) == 2
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`add_setting` should convert the key to lowercase.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light"}
|
||||
result = add_setting(settings_in_test, ("VOLUME", "high"))
|
||||
assert "volume" in settings_in_test
|
||||
assert "VOLUME" not in settings_in_test
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`add_setting` should convert the value to lowercase.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light"}
|
||||
result = add_setting(settings_in_test, ("volume", "HIGH"))
|
||||
assert settings_in_test["volume"] == "high"
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`add_setting({'theme': 'light'}, ('THEME': 'dark'))` should return the error message `Setting 'theme' already exists! Cannot add a new setting with this name.`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light", "language": "English"}
|
||||
result = add_setting(settings_in_test, ("THEME", "dark"))
|
||||
expected_msg = "Setting 'theme' already exists! Cannot add a new setting with this name."
|
||||
assert result == expected_msg
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`add_setting({'theme': 'light'}, ('volume', 'high')` should add a new key-value pair and return the success message `Setting 'volume' added with value 'high' successfully!`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light"}
|
||||
result = add_setting(settings_in_test, ("volume", "high"))
|
||||
expected_msg = "Setting 'volume' added with value 'high' successfully!"
|
||||
assert result == expected_msg
|
||||
assert settings_in_test["volume"] == "high"
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`add_setting` should correctly add the given key-value pair to the dictionary.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light"}
|
||||
result = add_setting(settings_in_test, ("os", "Ubuntu"))
|
||||
assert "os" in settings_in_test
|
||||
assert settings_in_test["os"] == "ubuntu"
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
You should define a function named `update_setting`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
assert _Node(_code).has_function('update_setting')
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
The `update_setting` function should have two parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
import inspect
|
||||
sig = inspect.signature(update_setting)
|
||||
assert len(sig.parameters) == 2
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
The `update_setting` function should convert key to lowercase.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light", "language": "English"}
|
||||
result = update_setting(settings_in_test, ("THEME", "dark"))
|
||||
assert "THEME" not in settings_in_test
|
||||
assert "theme" in settings_in_test
|
||||
assert settings_in_test["theme"] == "dark"
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
The `update_setting` function should convert value to lowercase.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light"}
|
||||
# Use the existing "theme" key but an uppercase value
|
||||
result = update_setting(settings_in_test, ("theme", "HIGH"))
|
||||
assert settings_in_test["theme"] == "high"
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`update_setting({'theme': 'light'}, ('theme', 'dark'))` should update an existing key and return the success message `Setting 'theme' updated to 'dark' successfully!`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light", "language": "English"}
|
||||
result = update_setting(settings_in_test, ("theme", "dark"))
|
||||
expected_msg = "Setting 'theme' updated to 'dark' successfully!"
|
||||
assert result == expected_msg
|
||||
assert settings_in_test["theme"] == "dark"
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`update_setting({'theme': 'light'}, ('volume', 'high'))` should return the error message `Setting 'volume' does not exist! Cannot update a non-existing setting.` when the key doesn't exist.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light"}
|
||||
result = update_setting(settings_in_test, ("volume", "high"))
|
||||
expected_msg = "Setting 'volume' does not exist! Cannot update a non-existing setting."
|
||||
assert result == expected_msg
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`update_setting` should correctly update the given key-value pair in the dictionary.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light", "language": "English"}
|
||||
result = update_setting(settings_in_test, ("language", "spanish"))
|
||||
assert "language" in settings_in_test
|
||||
assert settings_in_test["language"] == "spanish"
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
You should define a function named `delete_setting`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
assert _Node(_code).has_function('delete_setting')
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
The `delete_setting` function should have two parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
import inspect
|
||||
sig = inspect.signature(delete_setting)
|
||||
assert len(sig.parameters) == 2
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`delete_setting` should convert the key to lowercase.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light", "language": "English"}
|
||||
result = delete_setting(settings_in_test, "THEME")
|
||||
assert "theme" not in settings_in_test
|
||||
assert "THEME" not in settings_in_test
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`delete_setting({'theme': 'light'}, 'theme')` should remove the existing key and return the success message `Setting 'theme' deleted successfully!`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light", "language": "English"}
|
||||
result = delete_setting(settings_in_test, "theme")
|
||||
expected_msg = "Setting 'theme' deleted successfully!"
|
||||
assert result == expected_msg
|
||||
assert "theme" not in settings_in_test
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`delete_setting` should return the error message `Setting not found!` when the key doesn't exist.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light"}
|
||||
result = delete_setting(settings_in_test, "volume")
|
||||
expected_msg = "Setting not found!"
|
||||
assert result == expected_msg
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`delete_setting` should correctly remove the given key from the dictionary.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light", "language": "English"}
|
||||
result = delete_setting(settings_in_test, "language")
|
||||
assert "language" not in settings_in_test
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
You should define a function named `view_settings`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
assert _Node(_code).has_function('view_settings')
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
The `view_settings` function should have one parameter.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
import inspect
|
||||
sig = inspect.signature(view_settings)
|
||||
assert len(sig.parameters) == 1
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`view_settings` should return the message `No settings available.` if the given dictionary is empty.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
empty_settings = {}
|
||||
result = view_settings(empty_settings)
|
||||
expected_msg = "No settings available."
|
||||
assert result == expected_msg
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`view_settings` should return formatted settings for non-empty dictionary.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "dark", "notifications": "enabled", "volume": "high"}
|
||||
result = view_settings(settings_in_test)
|
||||
assert result.startswith("Current User Settings:")
|
||||
assert "Theme: dark" in result
|
||||
assert "Notifications: enabled" in result
|
||||
assert "Volume: high" in result
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`view_settings` should capitalize the first letter of each setting name.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "dark", "volume": "high"}
|
||||
result = view_settings(settings_in_test)
|
||||
assert "Theme:" in result
|
||||
assert "Volume:" in result
|
||||
assert "theme:" not in result
|
||||
assert "volume:" not in result
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
`view_settings` should display the correct results and end with a newline character.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`
|
||||
settings_in_test = {"theme": "light", "language": "English", "notifications": "enabled"}
|
||||
result = view_settings(settings_in_test)
|
||||
assert result == "Current User Settings:\\nTheme: light\\nLanguage: English\\nNotifications: enabled\\n"
|
||||
`)
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```py
|
||||
def add_setting(settings, key_value):
|
||||
key, value = key_value
|
||||
key = key.lower()
|
||||
value = value.lower()
|
||||
if key in settings:
|
||||
return f"Setting '{key}' already exists! Cannot add a new setting with this name."
|
||||
else:
|
||||
settings[key] = value
|
||||
return f"Setting '{key}' added with value '{value}' successfully!"
|
||||
|
||||
def update_setting(settings, key_value):
|
||||
key, value = key_value
|
||||
key = key.lower()
|
||||
value = value.lower()
|
||||
if key in settings:
|
||||
settings[key] = value
|
||||
return f"Setting '{key}' updated to '{value}' successfully!"
|
||||
else:
|
||||
return f"Setting '{key}' does not exist! Cannot update a non-existing setting."
|
||||
|
||||
def delete_setting(settings, key):
|
||||
key = key.lower()
|
||||
if key in settings:
|
||||
del settings[key]
|
||||
return f"Setting '{key}' deleted successfully!"
|
||||
else:
|
||||
return "Setting not found!"
|
||||
|
||||
def view_settings(settings):
|
||||
if not settings:
|
||||
return "No settings available."
|
||||
else:
|
||||
settings_str = "Current User Settings:\n"
|
||||
for key, value in settings.items():
|
||||
settings_str += f"{key.capitalize()}: {value}\n"
|
||||
return settings_str
|
||||
|
||||
test_settings = {
|
||||
"theme": "light",
|
||||
"language": "English",
|
||||
"notifications": "enabled"
|
||||
}
|
||||
|
||||
print(add_setting(test_settings, ("VOLUME", "HIGH")))
|
||||
print(update_setting(test_settings, ("theme", "dark")))
|
||||
print(delete_setting(test_settings, "language"))
|
||||
print(view_settings(test_settings))
|
||||
```
|
||||
@@ -1308,7 +1308,7 @@
|
||||
{ "dashedName": "lecture-working-with-dictionaries-and-sets" },
|
||||
{ "dashedName": "lecture-working-with-modules" },
|
||||
{ "dashedName": "workshop-medical-data-validator" },
|
||||
{ "dashedName": "lab-placeholder-dictionaries-and-sets" },
|
||||
{ "dashedName": "lab-user-configuration-manager" },
|
||||
{ "dashedName": "review-dictionaries-and-sets" },
|
||||
{ "dashedName": "quiz-dictionaries-and-sets" }
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user