diff --git a/_extensions/pyodide/qpyodide-document-engine-initialization.js b/_extensions/pyodide/qpyodide-document-engine-initialization.js
index 1926571..ac69fe8 100644
--- a/_extensions/pyodide/qpyodide-document-engine-initialization.js
+++ b/_extensions/pyodide/qpyodide-document-engine-initialization.js
@@ -32,11 +32,21 @@ globalThis.qpyodideInstance = await import(
// Setup a namespace for global scoping
// await loadedPyodide.runPythonAsync("globalScope = {}");
+
+ // Update status to reflect the next stage of the procedure
+ qpyodideUpdateStatusHeaderSpinner("Initializing Python Packages");
// Load the `micropip` package to allow installation of packages.
await mainPyodide.loadPackage("micropip");
+ await mainPyodide.runPythonAsync(`import micropip`);
+
+ // Load the `pyodide_http` package to shim uses of `requests` and `urllib3`.
+ // This allows for `pd.read_csv(url)` to work flawlessly.
+ // Details: https://github.com/coatless-quarto/pyodide/issues/9
+ await mainPyodide.loadPackage("pyodide_http");
await mainPyodide.runPythonAsync(`
- import micropip
+ import pyodide_http
+ pyodide_http.patch_all() # Patch all libraries
`);
// Load the `matplotlib` package with necessary environment hook
@@ -53,11 +63,12 @@ globalThis.qpyodideInstance = await import(
qpyodideSetInteractiveButtonState(
` Run Code`,
true
- );
+ );
- if (qpyodideShowStartupMessage) {
- qpyodideStartupMessage.innerText = "🟢 Ready!"
- }
+ // Set document status to viable
+ qpyodideUpdateStatusHeader(
+ "🟢 Ready!"
+ );
// Assign Pyodide into the global environment
globalThis.mainPyodide = mainPyodide;
diff --git a/_extensions/pyodide/qpyodide-document-status.js b/_extensions/pyodide/qpyodide-document-status.js
index 5fff260..bb53113 100644
--- a/_extensions/pyodide/qpyodide-document-status.js
+++ b/_extensions/pyodide/qpyodide-document-status.js
@@ -18,11 +18,22 @@ globalThis.qpyodideUpdateStatusMessage = function(message) {
// Function to update the status message
globalThis.qpyodideUpdateStatusHeader = function(message) {
- qpyodideStartupMessage.innerHTML = `
+
+ if (!qpyodideShowStartupMessage) return;
+
+ qpyodideStartupMessage.innerHTML = message;
+}
+
+// Status header update with customized spinner message
+globalThis.qpyodideUpdateStatusHeaderSpinner = function(message) {
+
+ qpyodideUpdateStatusHeader(`
- ${message}`;
+ ${message}
+ `);
}
+
// Function that attaches the document status message
function qpyodideDisplayStartupMessage(showStartupMessage) {
if (!showStartupMessage) {
diff --git a/docs/qpyodide-code-cell-demo.qmd b/docs/qpyodide-code-cell-demo.qmd
index de992c1..f2688d0 100644
--- a/docs/qpyodide-code-cell-demo.qmd
+++ b/docs/qpyodide-code-cell-demo.qmd
@@ -125,7 +125,22 @@ num_list = [1, 2, 3]
## Load a package
-We've enabled _dynamic_ package detection to handle importing packages into the environment. The _dynamic_ part comes from detecting whether a non-core Python package is used, installing, and, then, importing it.
+There are two types of Python packages that will work within an interactive cell.
+
+- pure Python packages
+ - denoted by `*py3-none-any.whl` on PyPI
+- Python packages compiled for Pyodide
+ - denoted by `*-cp310-cp310-emscripten_3_1_27_wasm32.whl` that require a specific Python and Emscripten versions
+
+The latter option makes up part of the Pyodide "core" or "base" set of Python packages.
+
+:::{.callout-important}
+Not all functionality of a Python package may be available in the browser due to limitations or different versions being present.
+:::
+
+### Loading a Pyodide core package
+
+For packages that are part of [Pyodide core](https://pyodide.org/en/stable/usage/packages-in-pyodide.html), we've enabled _dynamic_ package detection to handle importing packages into the environment. The _dynamic_ part comes from detecting whether a Python package is being used through an import statement and automatically taking care of the installation process behind the scenes.
:::{.callout-note}
Importing a package for the first time will require more time. Subsequent import statements will be resolve quicker.
@@ -173,7 +188,7 @@ from palmerpenguins import load_penguins
# Load data in the package
penguins = load_penguins()
-# Display th e first 5 rows of the data using Pandas
+# Display the first 5 rows of the data using Pandas
penguins.head()
```
@@ -190,3 +205,13 @@ y = [-5, 8, 9, 4]
plt.plot(x, y)
plt.show()
```
+
+## External Data
+
+Interactive cells also allow for a limited subset of operations when working with external data. For example, we can use Pandas' `read_csv()` function to ingest data from a URL.
+```{pyodide-python}
+import pandas as pd
+
+df = pd.read_csv("https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv")
+df.head()
+```
\ No newline at end of file
diff --git a/docs/qpyodide-release-notes.qmd b/docs/qpyodide-release-notes.qmd
index 0ccb258..af7f81b 100644
--- a/docs/qpyodide-release-notes.qmd
+++ b/docs/qpyodide-release-notes.qmd
@@ -19,6 +19,13 @@ format:
- New code cell option that set the interactive cell to be read-only. ([#4](https://github.com/coatless-quarto/pyodide/issues/4))
+## Changes
+
+- We now load the `micropip` and `pyodide_http` packages during document initialization.
+ - `micropip` package allows for installation of pure Python or Pyodide-compiled Python packages.
+ ([#3](https://github.com/coatless-quarto/pyodide/issues/3))
+ - `pyodide_http` provides the necessary shims to ensure uses of `requests` and `urllib3` are
+ able to be processed instead of returning a URL error. ([#9](https://github.com/coatless-quarto/pyodide/issues/9))
# 0.0.1: What does the Python Say? (02-19-2024)
diff --git a/tests/qpyodide-test-url.qmd b/tests/qpyodide-test-url.qmd
new file mode 100644
index 0000000..8cfe2e4
--- /dev/null
+++ b/tests/qpyodide-test-url.qmd
@@ -0,0 +1,15 @@
+---
+title: "Test: Accessing Data via URL"
+format: html
+filters:
+ - pyodide
+---
+
+This test is designed to check if HTTP requests are shimmed so that the operation can be performed.
+
+```{pyodide-python}
+import pandas as pd
+
+df = pd.read_csv("https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv")
+df.head()
+```
\ No newline at end of file