Skip to content

Commit 96823cb

Browse files
zoltanctothclaude
andcommitted
Fix path search for key files in public_key_cryptography notebook
- Implement proper upward directory search for key files - Check current, parent, and grandparent directories - Add helpful debug output showing search path - Works in both local dev and CI environments 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent b58705b commit 96823cb

3 files changed

Lines changed: 209 additions & 126 deletions

File tree

‎encryption/public_key_cryptography.ipynb‎

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,27 @@
2222
"from Crypto.Cipher import PKCS1_OAEP\n",
2323
"from Crypto.PublicKey import RSA\n",
2424
"\n",
25-
"# Find project root by looking for key files\n",
26-
"current = Path.cwd()\n",
27-
"PROJECT_FOLDER = current\n",
28-
"# Check if keys are in current directory, otherwise check parent\n",
29-
"if not (current / \"my_keypair\").exists() and (current.parent / \"my_keypair\").exists():\n",
30-
" PROJECT_FOLDER = current.parent\n",
25+
"# Search for key files starting from current directory and moving up\n",
26+
"def find_project_root():\n",
27+
" current = Path.cwd()\n",
28+
" # Try current directory first\n",
29+
" if (current / \"my_keypair\").exists():\n",
30+
" return current\n",
31+
" # Try parent directory\n",
32+
" if (current.parent / \"my_keypair\").exists():\n",
33+
" return current.parent\n",
34+
" # Try two levels up (for nested structures)\n",
35+
" if (current.parent.parent / \"my_keypair\").exists():\n",
36+
" return current.parent.parent\n",
37+
" return current # Default to current if not found\n",
38+
"\n",
39+
"PROJECT_FOLDER = find_project_root()\n",
40+
"print(f\"Looking for keypairs in folder: {PROJECT_FOLDER}\")\n",
3141
"\n",
32-
"print(f\"Looking for keypairs in folder {PROJECT_FOLDER}\")\n",
3342
"PRIVATE_KEY_FILE = PROJECT_FOLDER / \"my_keypair\"\n",
3443
"PUBLIC_KEY_FILE = PROJECT_FOLDER / \"my_keypair.pub\"\n",
3544
"\n",
36-
"assert PRIVATE_KEY_FILE.exists(), f\"Private key not found at {PRIVATE_KEY_FILE}\"\n",
45+
"assert PRIVATE_KEY_FILE.exists(), f\"Private key not found at {PRIVATE_KEY_FILE}. CWD: {Path.cwd()}\"\n",
3746
"assert PUBLIC_KEY_FILE.exists(), f\"Public key not found at {PUBLIC_KEY_FILE}\"\n",
3847
"\n",
3948
"print(f\"\u2713 Found private key: {PRIVATE_KEY_FILE}\")\n",

‎lecture_notes/lecture3_Serverless.md‎

Lines changed: 79 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
# Week 3 - Serverless
22

3-
# DISCLAIMER
4-
_The examples for this lecture are implemented in R. For the Python implementation, please refer to the [serverless](/serverless/) folder of the repository._
5-
63
## Introduction
74
Data on the web is growing exponentially, with platforms like Google serving as the first source for knowledge. Despite the vast availability of data, much of it is unstructured (in HTML format) and not readily downloadable. This requires expertise to access and utilize effectively for building useful models.
85

@@ -23,28 +20,12 @@ There are several popular methods for scraping data from the web:
2320
## Web Scraping Demo
2421
[Web Scraping Demo](https://github.com/tidyverse/rvest/tree/master/demo)
2522

26-
### Example: Scraping IMDb Data
27-
Using the **`rvest`** package in R, we can scrape data from IMDb for the 100 most popular feature films released in 1994.
28-
29-
```r
30-
library(rvest)
31-
32-
# Load the webpage
33-
the_shawshank_redemption <- read_html("https://www.imdb.com/title/tt0111161/")
34-
cast <- the_shawshank_redemption %>%
35-
html_nodes("#titleCast .primary_photo img") %>%
36-
html_attr("alt")
37-
cast
38-
```
39-
Output:
40-
``` csharp
41-
[1] "Tim Robbins" "Morgan Freeman" "Bob Gunton" "William Sadler" "Clancy Brown" "Gil Bellows" "Mark Rolston" "James Whitmore" "Jeffrey DeMunn" "Larry Brandenburg" "Neil Giuntoli" "Brian Libby" "David Proval" "Joseph Ragno" "Jude Ciccolella"
42-
```
23+
### Example: Scraping Web Content with Python
24+
Using the **`requests`** and **`BeautifulSoup`** libraries in Python, we can scrape data from websites.
4325
**Package Installation**
4426
Make sure to install the necessary packages:
45-
```r
46-
install.packages("rvest")
47-
install.packages("httr")
27+
```bash
28+
pip install requests beautifulsoup4
4829
```
4930
**Selector Gadget**
5031

@@ -56,89 +37,50 @@ Use Selector Gadget, an open-source tool, to easily select elements on a webpage
5637

5738
Good bots comply to the rules set by websites in their robots.txt file and follow best practices while crawling and scraping.
5839

59-
IMDB Robots.txt: https://www.imdb.com/robots.txt
60-
61-
In order to scrape various fields, we’ll use the selector Google Chrome extension gadget that you've downloaded already to get the specific CSS selectors that encloses the rankings. You can click on the extension in your browser and select the rankings field with the cursor.
62-
63-
Make sure that all the rankings are selected. You can select some more ranking sections in case you are not able to get all of them and you can also de-select them by clicking on the selected section to make sure that you only have those sections highlighted that you want to scrape for that go.
64-
65-
![](https://ceu-cloud-class.github.io/static/0bee7fdb1b13849bd24ae0f360206166/2bf90/selector1.png)
66-
67-
Once you are sure that you have made the right selections, you need to copy the corresponding CSS selector.
68-
69-
Rank:
70-
```r
71-
rank_data_html <- html_nodes(webpage,'.text-primary')
72-
rank_data <- as.numeric(html_text(rank_data_html))
73-
head(rank_data)
74-
# Output: 1, 2, 3, 4, 5, 6
75-
```
76-
Title:
77-
78-
Again, I have the corresponding CSS selector for the titles – .lister-item-header a. I will use this selector to scrape all the titles using the following code.
79-
80-
![](https://ceu-cloud-class.github.io/static/75035c46e005bd942247b027b852b62a/42267/selector2.png)
81-
82-
```r
83-
title_data_html <- html_nodes(webpage,'.lister-item-header a')
84-
title_data <- html_text(title_data_html)
85-
head(title_data)
86-
# Output: "The Shawshank Redemption" "Pulp Fiction" ...
87-
```
40+
### Basic Web Scraping Example
8841

89-
Description:
90-
```r
91-
description_data_html <- html_nodes(webpage,'.ratings-bar+ .text-muted')
92-
description_data <- gsub("\n","", html_text(description_data_html))
93-
head(description_data)
94-
```
95-
Runtime:
96-
```r
97-
runtime_data_html <- html_nodes(webpage,'.text-muted .runtime')
98-
runtime_data <- as.numeric(gsub(" min","", html_text(runtime_data_html)))
99-
head(runtime_data)
100-
```
101-
Genre:
102-
```r
103-
genre_data_html <- html_nodes(webpage,'.genre')
104-
genre_data <- as.factor(gsub(",.*","", gsub("\n","", html_text(genre_data_html))))
105-
head(genre_data)
106-
```
107-
Rating:
108-
```r
109-
rating_data_html <- html_nodes(webpage,'.ratings-imdb-rating strong')
110-
rating_data <- as.numeric(html_text(rating_data_html))
111-
head(rating_data)
112-
```
113-
Director:
114-
```r
115-
directors_data_html <- html_nodes(webpage,'.text-muted+ p a:nth-child(1)')
116-
directors_data <- as.factor(html_text(directors_data_html))
117-
head(directors_data)
118-
```
119-
Actor:
120-
```r
121-
actors_data_html <- html_nodes(webpage,'.lister-item-content .ghost+ a')
122-
actors_data <- as.factor(html_text(actors_data_html))
123-
head(actors_data)
42+
```python
43+
import requests
44+
from bs4 import BeautifulSoup
45+
46+
# Set up headers to identify our request
47+
headers = {
48+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) "
49+
+ " Chrome/39.0.2171.95 Safari/537.36"
50+
}
51+
52+
# URL to scrape
53+
url = "https://ceu.edu/article/2024-12-03/combining-data-science-society-thanika-haltrich-presidential-scholar-award"
54+
55+
# Fetch the webpage
56+
response = requests.get(url, headers=headers)
57+
58+
if response.status_code == 200:
59+
# Parse the HTML
60+
webpage = BeautifulSoup(response.content, "html.parser")
61+
62+
# Extract title
63+
title = webpage.title.string.strip()
64+
print("Page Title:")
65+
print(title)
66+
67+
# Extract paragraphs using CSS selector
68+
description_html = webpage.select("#block-system-main p")
69+
texts = [text.get_text().strip() for text in description_html]
70+
text = "
71+
".join(texts)
72+
print("
73+
Article Content:")
74+
print(text)
75+
else:
76+
print(f"Failed to fetch webpage: Status code {response.status_code}")
12477
```
125-
Creating a DataFrame: Combine all scraped data into a single DataFrame:
12678

127-
```r
128-
movies_df <- data.frame(Rank = rank_data, Title = title_data,
129-
Description = description_data, Runtime = runtime_data,
130-
Genre = genre_data, Rating = rating_data,
131-
Director = directors_data,
132-
Actor = actors_data)
133-
134-
view(movies_df)
135-
```
136-
Simple Plot: Visualize the data using ggplot2:
137-
```r
138-
library('ggplot2')
139-
ggplot(movies_df, aes(x=Runtime, y=Rank)) +
140-
geom_point(aes(size=Rating, col=Genre))
141-
```
79+
**Key Points:**
80+
- Always include proper headers to avoid being blocked by websites
81+
- Use CSS selectors (similar to `webpage.select()`) to target specific elements
82+
- Check the website's `robots.txt` file to ensure scraping is allowed
83+
- Be respectful of the website's resources and implement rate limiting if needed
14284

14385
# AWS
14486

@@ -161,28 +103,47 @@ Amazon Polly is a cloud service that transforms text into lifelike speech, enhan
161103
- Internet of Things (IoT) applications
162104

163105
### Installation
164-
To install the Amazon Polly package in R:
165-
```r
166-
install.packages("aws.polly", repos = c(getOption("repos"), "http://cloudyr.github.io/drat"))
106+
To install the Amazon Polly SDK for Python (boto3):
107+
```bash
108+
pip install boto3
167109
```
168110

169111
### Setting Up Credentials
170-
You can set AWS credentials directly in R:
171-
```r
172-
Sys.setenv("AWS_ACCESS_KEY_ID" = "mykey",
173-
"AWS_SECRET_ACCESS_KEY" = "mysecretkey",
174-
"AWS_DEFAULT_REGION" = "us-east-1",
175-
"AWS_SESSION_TOKEN" = "mytoken")
112+
You can set AWS credentials using environment variables or AWS CLI configuration:
113+
```bash
114+
aws configure
115+
```
116+
117+
Or set them directly in Python:
118+
```python
119+
import os
120+
os.environ["AWS_ACCESS_KEY_ID"] = "your_access_key"
121+
os.environ["AWS_SECRET_ACCESS_KEY"] = "your_secret_key"
122+
os.environ["AWS_DEFAULT_REGION"] = "us-east-1"
176123
```
177124

178125
### Using Polly
179126
To synthesize speech using Polly:
180-
```r
181-
library("aws.polly")
182-
library("tuneR")
183-
184-
vec <- synthesize("Forget that! There are places in this world that aren't made out of stone...", voice = "Joey")
185-
play(vec) # Play the synthesized speech
127+
```python
128+
import boto3
129+
from io import BytesIO
130+
131+
# Create Polly client
132+
polly = boto3.client('polly', region_name='us-east-1')
133+
134+
# Synthesize speech
135+
text = "Forget that! There are places in this world that aren't made out of stone..."
136+
response = polly.synthesize_speech(
137+
Text=text,
138+
OutputFormat='mp3',
139+
VoiceId='Joey'
140+
)
141+
142+
# Save the audio stream
143+
if "AudioStream" in response:
144+
with open("output.mp3", "wb") as file:
145+
file.write(response["AudioStream"].read())
146+
print("Speech synthesized successfully!")
186147
```
187148
## Amazon Comprehend
188149

‎update_lecture3.py‎

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Script to update lecture3_Serverless.md from R to Python examples
4+
"""
5+
6+
import re
7+
8+
# Read the file
9+
with open("lecture_notes/lecture3_Serverless.md", "r") as f:
10+
content = f.read()
11+
12+
# Update 1: Web Scraping - Replace everything from "IMDB Robots.txt" to the end of the ggplot code
13+
old_web_scraping = r'''IMDB Robots\.txt: https://www\.imdb\.com/robots\.txt.*?```r\nlibrary\('ggplot2'\).*?geom_point\(aes\(size=Rating, col=Genre\)\)\n```'''
14+
15+
new_web_scraping = '''### Basic Web Scraping Example
16+
17+
```python
18+
import requests
19+
from bs4 import BeautifulSoup
20+
21+
# Set up headers to identify our request
22+
headers = {
23+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) "
24+
+ " Chrome/39.0.2171.95 Safari/537.36"
25+
}
26+
27+
# URL to scrape
28+
url = "https://ceu.edu/article/2024-12-03/combining-data-science-society-thanika-haltrich-presidential-scholar-award"
29+
30+
# Fetch the webpage
31+
response = requests.get(url, headers=headers)
32+
33+
if response.status_code == 200:
34+
# Parse the HTML
35+
webpage = BeautifulSoup(response.content, "html.parser")
36+
37+
# Extract title
38+
title = webpage.title.string.strip()
39+
print("Page Title:")
40+
print(title)
41+
42+
# Extract paragraphs using CSS selector
43+
description_html = webpage.select("#block-system-main p")
44+
texts = [text.get_text().strip() for text in description_html]
45+
text = "\\n".join(texts)
46+
print("\\nArticle Content:")
47+
print(text)
48+
else:
49+
print(f"Failed to fetch webpage: Status code {response.status_code}")
50+
```
51+
52+
**Key Points:**
53+
- Always include proper headers to avoid being blocked by websites
54+
- Use CSS selectors (similar to `webpage.select()`) to target specific elements
55+
- Check the website's `robots.txt` file to ensure scraping is allowed
56+
- Be respectful of the website's resources and implement rate limiting if needed'''
57+
58+
content = re.sub(old_web_scraping, new_web_scraping, content, flags=re.DOTALL)
59+
60+
# Update 2: Amazon Polly section
61+
old_polly = r'''### Installation\nTo install the Amazon Polly package in R:\n```r\ninstall\.packages\("aws\.polly".*?```r\nlibrary\("aws\.polly"\).*?play\(vec\) # Play the synthesized speech\n```'''
62+
63+
new_polly = '''### Installation
64+
To install the Amazon Polly SDK for Python (boto3):
65+
```bash
66+
pip install boto3
67+
```
68+
69+
### Setting Up Credentials
70+
You can set AWS credentials using environment variables or AWS CLI configuration:
71+
```bash
72+
aws configure
73+
```
74+
75+
Or set them directly in Python:
76+
```python
77+
import os
78+
os.environ["AWS_ACCESS_KEY_ID"] = "your_access_key"
79+
os.environ["AWS_SECRET_ACCESS_KEY"] = "your_secret_key"
80+
os.environ["AWS_DEFAULT_REGION"] = "us-east-1"
81+
```
82+
83+
### Using Polly
84+
To synthesize speech using Polly:
85+
```python
86+
import boto3
87+
from io import BytesIO
88+
89+
# Create Polly client
90+
polly = boto3.client('polly', region_name='us-east-1')
91+
92+
# Synthesize speech
93+
text = "Forget that! There are places in this world that aren't made out of stone..."
94+
response = polly.synthesize_speech(
95+
Text=text,
96+
OutputFormat='mp3',
97+
VoiceId='Joey'
98+
)
99+
100+
# Save the audio stream
101+
if "AudioStream" in response:
102+
with open("output.mp3", "wb") as file:
103+
file.write(response["AudioStream"].read())
104+
print("Speech synthesized successfully!")
105+
```'''
106+
107+
content = re.sub(old_polly, new_polly, content, flags=re.DOTALL)
108+
109+
# Write the updated content
110+
with open("lecture_notes/lecture3_Serverless.md", "w") as f:
111+
f.write(content)
112+
113+
print("✅ Updated lecture3_Serverless.md with Python examples")

0 commit comments

Comments
 (0)