diff --git a/clean-modular-code/activity-3/clean-code-activity-3.md b/clean-modular-code/activity-3/clean-code-activity-3.md
index 83d498e..d9a29b7 100644
--- a/clean-modular-code/activity-3/clean-code-activity-3.md
+++ b/clean-modular-code/activity-3/clean-code-activity-3.md
@@ -62,7 +62,7 @@ As you make decisions about adding checks to your code, weigh the value of using
# This fails with a FileNotFound Error
from pathlib import Path
-file_path = Path("aadata-bad-path") / "2022-03-joss-publications.json"
+file_path = Path("data-bad-path") / "2022-03-joss-publications.json"
try:
print(file_path)
@@ -71,6 +71,8 @@ try:
json_clean = pd.json_normalize(json_data)
except:
print("This doesn't fail fast, it only prints a message")
+
+print("Look, i keep running after the try/except block which means I didn't fail")
```
+++ {"editable": true, "slideshow": {"slide_type": ""}}
@@ -83,7 +85,7 @@ If you are processing specific data in your workflow, then ensuring your code ca
If your code doesn't [fail fast](fail-fast) with a useful error message, and it continues to run and fails later, it will potentially confuse a user. The error that will likely be raised later will likely not alert the user that the issue is actually missing data vs something else.
-This will then mislead someone when trying to troubleshoot your code.
+This will then mislead someone when trying to troubleshoot your code.
+++
@@ -123,7 +125,7 @@ Turn the code below into a function.
Modify the function below so it raises catches the errror and prints a custom error but does not
stop your code from continuing to run.
-Consider the difference between the funciton the funciton that you created above that stops your code from running by raising an exception compared to this code that prints a statement for the user.
+Consider the difference between the funciton the funciton that you created above that stops your code from running by raising an exception compared to this code that prints a statement for the user.
```{code-cell} ipython3
---
diff --git a/clean-modular-code/clean-code-present.md b/clean-modular-code/clean-code-present.md
index d305c19..3aeef2e 100644
--- a/clean-modular-code/clean-code-present.md
+++ b/clean-modular-code/clean-code-present.md
@@ -13,7 +13,7 @@ kernelspec:
+++ {"editable": true, "slideshow": {"slide_type": "slide"}}
-# Clean, Modular Code
+# Clean, Modular Code: overview
+++ {"editable": true, "slideshow": {"slide_type": ""}}
@@ -23,10 +23,8 @@ kernelspec:
* Use [expressive object names](python-expressive-code)
* [Make your code DRY](dry-code)
-
+++ {"editable": true, "slideshow": {"slide_type": "slide"}, "jp-MarkdownHeadingCollapsed": true}
-
### PEP 8 & consistent code format
* Generally accepted rules for code format: PEP 8
@@ -35,13 +33,13 @@ kernelspec:
+++ {"editable": true, "slideshow": {"slide_type": "skip"}}
-
## Notes
-
```{code-cell} ipython3
---
editable: true
+jupyter:
+ source_hidden: true
slideshow:
slide_type: ''
---
@@ -77,10 +75,8 @@ if x:
* Black
* Ruff
-
+++ {"editable": true, "slideshow": {"slide_type": "slide"}, "jp-MarkdownHeadingCollapsed": true}
-
#### [Other tools to consider](tools-code-style)
* `pre-commit` hooks: use with .git; apply every time you commit changes
@@ -95,7 +91,11 @@ if x:
+++ {"editable": true, "slideshow": {"slide_type": "slide"}}
-
+:::{figure} /images/clean-code/clean-code-expressive-variable-names-basmati-rice.png
+:alt: "Image showing a large see-through Tupperware container with cookies in it but a label that says Basmati Rice."
+
+A large see-through Tupperware container labeled "Basmati Rice" containing cookies.
+:::
```{code-cell} ipython3
---
@@ -194,14 +194,14 @@ Three strategies:
+++ {"editable": true, "slideshow": {"slide_type": "slide"}}
-## Document as you go
+### Document as you go
* Make it a habit
* It's easier to do it as you work!
+++ {"editable": true, "slideshow": {"slide_type": "slide"}}
-## Document your code
+#### Document your code
Add a docstring to the top of any script or module that explains the intent of the code.
@@ -313,7 +313,7 @@ help(add_num)
+++ {"editable": true, "slideshow": {"slide_type": "slide"}}
-## Modularize your code
+### Modularize your code
Functions make code easier to read, test, and maintain.
@@ -351,7 +351,7 @@ for num in numbers:
+++ {"editable": true, "slideshow": {"slide_type": "slide"}}
-## Reproducibility: Create dynamic paths
+## Make your code reproducibe across machines with dynamic paths
* Paths on Windows are different than MAC/Linux
* Using `Path` (or `os`)
@@ -384,20 +384,19 @@ print(path)
## Tests & checks
-* Usability sometimes means failing (gracefully and with intention).
-
+* Usability sometimes means failing (gracefully and with intention).
+++ {"editable": true, "slideshow": {"slide_type": "slide"}}
-### Strategies
-* Fail fast (with useful error messages)
-* try/except blocks: handle errors (exceptions)
-* Conditionals to optimize and redirect workflows
+### 3 Strategies
-+++ {"editable": true, "slideshow": {"slide_type": "slide"}}
+* **Fail fast** (with useful error messages)
+* **try/except blocks:** handle errors (exceptions)
+* **Conditionals** to optimize and redirect workflows
-## Fail fast
++++ {"editable": true, "slideshow": {"slide_type": "slide"}}
+### Fail fast
```{code-cell} ipython3
---
@@ -423,6 +422,13 @@ with file_path.open("r") as json_file:
df = pd.json_normalize(json_data)
```
+When your code doesn't fail fast, it might fail somewhere different.
+In this case, `.glob` can't find any files so the list of paths is empty.
+
+In this case, the file can't be opened but it failes because file_path is an
+empty list when the real problem is it's missing fail paths. This type of
+error is confusing to a user and will take longer to debug.
+
```{code-cell} ipython3
---
editable: true
@@ -439,7 +445,7 @@ import pandas as pd
# Create a list of json files
file_paths = list(Path(".").glob("*.json"))
# Open the first file
-with file_path[0].open("r") as json_file:
+with file_paths[0].open("r") as json_file:
json_data = json.load(json_file)
# Normalize the JSON data into a Pandas DataFrame
@@ -458,7 +464,7 @@ file_paths
+++ {"editable": true, "slideshow": {"slide_type": "slide"}}
-## Handle errors
+### Handle errors with try/excepts
* Anticipate errors a user may encounter when using your code.
* Redirect workflows by catching errors.
@@ -500,14 +506,19 @@ package_name = title.split(":")[0]
package_name
```
+In some cases, you may want to capture the error and return a default value
+(or do something else).
+
+:::{figure} /images/clean-code/try-except-blocks.png
+:alt: "An illustration showing a basic Python try and except block. Under “try:”, there is a green box with the text “Code runs as planned! Yay!”. Below that, under “except:”, there is a light yellow box with the text “Code fails, Do something else”. The image has a minimalist style with a small flower icon and a wavy line header at the top, and includes the pyOpenSci logo in the bottom right corner."
+:::
+
```{code-cell} ipython3
---
editable: true
slideshow:
slide_type: slide
---
-# In some cases, you may want to capture the error and return a default value
-# (or do something else)
title = 9999
try:
@@ -521,6 +532,8 @@ except AttributeError:
package_name
```
+In other cases you may want to intentionally raise an error with a custom message.
+
```{code-cell} ipython3
---
editable: true
@@ -528,7 +541,6 @@ slideshow:
slide_type: slide
tags: [raises-exception]
---
-# In others you may want to intentionally raise an error with a custom message.
title = 999
try:
@@ -543,8 +555,8 @@ package_name
+++ {"editable": true, "slideshow": {"slide_type": "slide"}}
-## Start activity three
+## You're ready for activity three
-Activity 3 is an interactive notebook you can work on in small groups.
+[Activity 3 is an interactive notebook](clean-code-activity-3) you can work on in small groups.
Work through the activities and ask questions!
diff --git a/images/clean-code/try-except-blocks.png b/images/clean-code/try-except-blocks.png
new file mode 100644
index 0000000..3cb49eb
Binary files /dev/null and b/images/clean-code/try-except-blocks.png differ