diff --git a/04_input_output.ipynb b/04_input_output.ipynb index 7a4c3153..0666a1d6 100644 --- a/04_input_output.ipynb +++ b/04_input_output.ipynb @@ -40,11 +40,11 @@ " - [Reading/Writing CSV files](#Reading/Writing-CSV-files)\n", " - [Quiz on CSV](#Quiz-on-CSV)\n", " - [Exercises](#Exercises)\n", - " - [Exercise 1: CSV to dictionary 🌶️](#Exercise-1:-CSV-to-dictionary-🌶️)\n", - " - [Exercise 2: Counting words 🌶️](#Exercise-2:-Counting-words-🌶️)\n", - " - [Exercise 3: Letter statistics 🌶️🌶️](#Exercise-3:-Letter-statistics-🌶️🌶️)\n", - " - [Exercise 4: Translating words 🌶️🌶️](#Exercise-4:-Translating-words-🌶️🌶️)\n", - " - [Exercise 5: Binary format 🌶️🌶️🌶️](#Exercise-5:-Binary-format-🌶️🌶️🌶️)" + " - [Exercise 1: CSV to dictionary](#Exercise-1:-CSV-to-dictionary)\n", + " - [Exercise 2: Counting words](#Exercise-2:-Counting-words)\n", + " - [Exercise 3: Letter statistics](#Exercise-3:-Letter-statistics)\n", + " - [Exercise 4: Translating words](#Exercise-4:-Translating-words)\n", + " - [Exercise 5: Binary format](#Exercise-5:-Binary-format)" ] }, { @@ -75,13 +75,7 @@ "- connecting to databases or other network services\n", "\n", "\n", - "The majority of these operations are covered by the Python standard library. We are going to see how to use them in this chapter.\n", - "\n", - "
current_path of the function solution_find_all_files\n",
@@ -613,8 +604,7 @@
"\n",
" Returns:\n",
" - The number of directories in the directory\n",
- " \"\"\"\n",
- " pass\n"
+ " \"\"\""
]
},
{
@@ -627,9 +617,9 @@
"### Reading from a file\n",
"\n",
"We now want to learn how to read text from a file. \n",
- "Let's see how to do this with an example: we want to open the file [hello.txt](./data/hello.txt) and read its contents.\n",
+ "Let's see how to do this with an example: we want to open the file [hello.txt](./tutorial/tests/data/hello.txt) and read its contents.\n",
"\n",
- "1. The path is already identified, we know the file is in `./data/hello.txt`. We save this in a variable `path`.\n",
+ "1. The path is already identified, we know the file is in [hello.txt](./tutorial/tests/data/hello.txt). We save this in a variable `path`.\n",
"2. We now can use the built-in function [`open`](https://docs.python.org/3/library/functions.html#open) to open the file. This function returns a [file object](https://docs.python.org/3/glossary.html#term-file-object) that we can use to further manipulate the file. To ensure we only open the file for reading, we pass the string \"r\" to the second argument of `open`.\n",
"3. Now we can read the contents using `read`, `readline` or `readlines`. `read` reads the whole file content into a single string, `readline` reads one line, while `readlines` reads the whole file content as a list of strings, one item per line in the file. This knowledge is useful when we only want to read part of a file or when the file is too big to fit in memory and we can only read parts.\n",
"4. Finally, we close the file using the `close` method on the file object.\n"
@@ -773,7 +763,7 @@
" Returns:\n",
" - A list of strings, each representing a line in the file\n",
" \"\"\"\n",
- " pass"
+ " return"
]
},
{
@@ -787,7 +777,7 @@
"- We use `write` to write a *string* to the file. Other types of object should be converted to string before being written.\n",
"\n",
"\n",
- "Let's see this in action by writing your name in a file called `me.txt` in [data](./data/)"
+ "Let's see this in action by writing your name in a file called `me.txt` in ```/tutorial/tests/data```"
]
},
{
@@ -902,8 +892,7 @@
"\n",
" Returns:\n",
" - None (writes to file)\n",
- " \"\"\"\n",
- " pass"
+ " \"\"\""
]
},
{
@@ -911,17 +900,23 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "2. Modify the function `solution_read_write_file` to read the lines from the file `input_file` and write them in the form `line, length`, to the file `output_file`. Here `line` is the line of text in `input_file` **without the line ending**, `length` is **number of characters** in that line **without the line separator**.\n",
- "If `input_file` contains these lines:\n",
+ "2. Modify the function `solution_read_write_file` to read the lines from the file `input_file` and write them in the form `line, length`, to the file `output_file`. Here `line` is the line of text in `input_file` **without the line ending (\\r\\n)**, `length` is **number of characters** in that line. The characters are added automatically by the operating system when reading a file. Windows uses **\\r\\n** whereas Linux and MacOS use only **\\n**. To remove the line ending characters, use ```strip(\"\\r\\n\")```, e.g.: ```line.strip(\"\\r\\n\")```.\n",
+ "\n",
+ " If `input_file` contains these lines:\n",
+ " \n",
" ```\n",
" first\n",
" second\n",
" ```\n",
+ " \n",
" we expect the output file to contain these lines:\n",
+ " \n",
" ```\n",
" first, 5\n",
" second, 6\n",
- " ```"
+ " ```\n",
+ " \n",
+ " Do not forget to add a **\\n** when writing lines in the file."
]
},
{
@@ -945,8 +940,7 @@
"\n",
" Returns:\n",
" - None (writes to file)\n",
- " \"\"\"\n",
- " pass"
+ " \"\"\""
]
},
{
@@ -1201,7 +1195,9 @@
"source": [
"message = \"Ciao\"\n",
"message_secret = bytes(message, \"utf-8\")\n",
- "[print(f\"The `uft8` codepoint is = {enc}, the bytes representation = {enc.to_bytes(4, 'little')}, the representation is {chr(enc)}\") for plain, enc in zip(message, message_secret)]"
+ "print_messages = [f\"The `uft8` codepoint is = {enc}, the bytes representation = {enc.to_bytes(4, 'little')}, the representation is {chr(enc)}\" for plain, enc in zip(message, message_secret)]\n",
+ "for msg in print_messages:\n",
+ " print(msg)"
]
},
{
@@ -1225,7 +1221,7 @@
"These packages are outside of the scope of this tutorial and will not be covered here.\n",
"\n",
"\n",
- "Let's see how to read csv files using `csv` with an example by reading [example.csv](./data/example.csv):"
+ "Let's see how to read csv files using `csv` with an example by reading [example.csv](./tutorial/tests/data/example.csv):"
]
},
{
@@ -1330,7 +1326,7 @@
"tags": []
},
"source": [
- "### Exercise 1: CSV to dictionary 🌶️"
+ "### Exercise 1: CSV to dictionary"
]
},
{
@@ -1340,6 +1336,8 @@
"tags": []
},
"source": [
+ "**Difficulty: 🌶️**\n",
+ "\n",
"Write a function that reads a CSV file and returns a dictionary.\n",
"\n",
"- The dictionary keys are in the first **column**\n",
@@ -1404,7 +1402,7 @@
" Returns:\n",
" - A dictionary with each row represented as a key, value pair\n",
" \"\"\"\n",
- " pass"
+ " return"
]
},
{
@@ -1414,7 +1412,7 @@
"tags": []
},
"source": [
- "### Exercise 2: Counting words 🌶️"
+ "### Exercise 2: Counting words"
]
},
{
@@ -1424,6 +1422,8 @@
"tags": []
},
"source": [
+ "**Difficulty: 🌶️**\n",
+ "\n",
"Write a function to read all the lines from `input_file` and count the number of words in the file. The solution should be a single number.\n",
"\n",
"For example, for the file\n",
@@ -1443,7 +1443,7 @@
" The file is available as the parameter input_file of solution_exercise2 function\n",
" \n",
" input() in the middle of a function?",
options={
"The function execution stops and it waits for the user to type an input": "Correct! Input is a blocking function which waits for user to enter a string in the console and press enter.",
- "The function continues its execution": "Wrong!",
+ "The function continues its execution": "Wrong! Input is a blocking function which waits for user input.",
},
correct_answer="The function execution stops and it waits for the user to type an input",
shuffle=True,
@@ -57,7 +57,7 @@ def __init__(self, title=""):
q1 = Question(
question="What does the operator / do when applied to two Pathlib.Path objects?",
options={
- "It removes the second path from the first": "Wrong, try it in the shell.",
+ "It removes the second path from the first": "Wrong, try it in a cell below.",
"It concatenates paths": "Correct, it lets you construct a path from different segments",
},
correct_answer="It concatenates paths",
@@ -68,7 +68,7 @@ def __init__(self, title=""):
question="If you use Pathlib, do you need to use different path separators on Windows and Linux to combine path segments?",
options={
"No, you can combine Pathlib.Path objects with /": "Correct! Pathlib will then generate the correct path for your OS.",
- "Yes": "Wrong! You can always use /",
+ "Yes": "Wrong! You can always use /",
},
correct_answer="No, you can combine Pathlib.Path objects with /",
shuffle=True,
@@ -78,7 +78,7 @@ def __init__(self, title=""):
question="""The path Pathlib.Path("./") represent a relative path. What location does it refer to?""",
options={
"Relative to the current working directory, the location of the current Python script being run": "Correct!",
- "Relative to the user's home directory": "Wrong!",
+ "Relative to the user's home directory": "Wrong! It is relative to the current working directory.",
},
correct_answer="Relative to the current working directory, the location of the current Python script being run",
shuffle=True,
diff --git a/tutorial/tests/data/example1.csv b/tutorial/tests/data/example1.csv
new file mode 100644
index 00000000..ab2340cd
--- /dev/null
+++ b/tutorial/tests/data/example1.csv
@@ -0,0 +1,24 @@
+<<<<<<< HEAD
+this,is,data
+0,1,2
+1,2,3
+2,3,4
+3,4,5
+4,5,6
+5,6,7
+6,7,8
+7,8,9
+8,9,10
+=======
+this,is,data
+0,1,2
+1,2,3
+2,3,4
+3,4,5
+4,5,6
+5,6,7
+6,7,8
+7,8,9
+8,9,10
+>>>>>>> 5bd589eb6742c15e877451b291ee8d04a405d4b1
+9,10,11
diff --git a/tutorial/tests/data/me.txt b/tutorial/tests/data/me.txt
new file mode 100644
index 00000000..e09cfaf8
--- /dev/null
+++ b/tutorial/tests/data/me.txt
@@ -0,0 +1 @@
+Simone
diff --git a/tutorial/tests/data/numbers.txt b/tutorial/tests/data/numbers.txt
new file mode 100644
index 00000000..8b1acc12
--- /dev/null
+++ b/tutorial/tests/data/numbers.txt
@@ -0,0 +1,10 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/tutorial/tests/data/output.txt b/tutorial/tests/data/output.txt
new file mode 100644
index 00000000..6a1b6037
Binary files /dev/null and b/tutorial/tests/data/output.txt differ
diff --git a/tutorial/tests/data/output1.txt b/tutorial/tests/data/output1.txt
new file mode 100644
index 00000000..f7dff7ae
Binary files /dev/null and b/tutorial/tests/data/output1.txt differ
diff --git a/tutorial/tests/test_04_input_output.py b/tutorial/tests/test_04_input_output.py
index b7b9fa69..13fb902c 100644
--- a/tutorial/tests/test_04_input_output.py
+++ b/tutorial/tests/test_04_input_output.py
@@ -254,10 +254,10 @@ def reference_exercise5(secret_file: pl.Path) -> str:
def test_exercise5(function_to_test):
message = get_data("secret_message.dat")
# Save the original content of the input file
- original_content = message.read_text()
+ original_content = message.read_bytes()
try:
assert function_to_test(message) == reference_exercise5(message)
finally:
# Reset the input file to its original content
- message.write_text(original_content)
+ message.write_bytes(original_content)