diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..3740c3a4
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,48 @@
+name: Release
+
+on:
+ push:
+ branches:
+ - main
+ workflow_dispatch:
+
+jobs:
+
+ release:
+ runs-on: ubuntu-latest
+
+ environment:
+ name: pypi
+ permissions:
+ id-token: write
+ contents: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v5
+
+ - name: Install uv
+ uses: astral-sh/setup-uv@v8.3.2
+ with:
+ python-version: "3.13"
+
+ - name: Build sdist and wheel
+ run: uv build
+
+ - name: Publish to PyPI
+ run: uv publish --trusted-publishing always
+
+ - name: Create release tag
+ # Adding a `--prerelease` flag in `gh release create` makes the release not
+ # show up as the latest stable release.
+ run: |
+ version="$(uv version --short)"
+ if uv run --no-project --with packaging python -c \
+ "import sys; from packaging.version import Version; sys.exit(0 if Version('${version}').is_prerelease else 1)"; then
+ prerelease="--prerelease"
+ else
+ prerelease=""
+ fi
+ gh release create "v${version}" --title "v${version}" --generate-notes ${prerelease}
+ env:
+ GH_TOKEN: ${{ github.token }}
diff --git a/docs/tutorial/basic_concepts.ipynb b/docs/tutorial/basic_concepts.ipynb
index cef2f819..0596b456 100644
--- a/docs/tutorial/basic_concepts.ipynb
+++ b/docs/tutorial/basic_concepts.ipynb
@@ -899,9 +899,7 @@
{
"cell_type": "markdown",
"metadata": {},
- "source": [
- "To simplify access to attribute values, the `Graph` class provides getter and setter functions that allow to access attribute values based on node identifiers. To access the feature `node_feature` of node `a`, we can write:"
- ]
+ "source": "To simplify access to attribute values, the `Graph` class provides getter and setter functions that allow to access attribute values based on node identifiers. To access the feature `node_class` of node `a`, we can write:"
},
{
"cell_type": "code",
@@ -919,9 +917,7 @@
"output_type": "execute_result"
}
],
- "source": [
- "g['node_class', 'a']"
- ]
+ "source": "g['node_class', 'a']"
},
{
"cell_type": "markdown",
@@ -1071,9 +1067,7 @@
{
"cell_type": "markdown",
"metadata": {},
- "source": [
- "By passing the name of the attribute, we can use edge attributes in the creation of the adjacency matrix. To create a sparse, weighted adjacency matrix that uses the `edge_weight` attribute of our graph object we can simply write:"
- ]
+ "source": "By passing the name of the attribute, we can use edge attributes in the creation of the adjacency matrix. To create a dense, weighted adjacency matrix that uses the `edge_weight` attribute of our graph object we can simply write:"
},
{
"cell_type": "code",
@@ -1154,7 +1148,7 @@
"source": [
"It is often convenient, to coalesce multi-edges into weighted single-edges, i.e. in the example above we may prefer a graph where each edge occurs once in the edge index, but the edge `a->b` has a weight attribute of two, while the two other edges have one.\n",
"\n",
- "In `pathpyG` we can do this by turning a graph into a weighted graph, which will coalesce edges and add an edge weight attribute that counts multi-edges in the original istance."
+ "In `pathpyG` we can do this by turning a graph into a weighted graph, which will coalesce edges and add an `edge_weight` attribute that counts multi-edges in the original instance."
]
},
{
@@ -1784,9 +1778,7 @@
{
"cell_type": "markdown",
"metadata": {},
- "source": [
- "Note that the `pp.io.graph_to_df` function only includes `edge`-level data. To also include `node`-level attributes, you need to create a separate `DataFrame` for those attributes."
- ]
+ "source": "Note that the `pp.io.graph_to_df` function only includes `edge`-level data. To also include `node`-level attributes, you need to create a separate `DataFrame` for those attributes. A specially-named column `v` of this `DataFrame` should contain node labels (or use a column called `index` for integer node index)."
},
{
"cell_type": "code",
@@ -1837,9 +1829,7 @@
{
"cell_type": "markdown",
"metadata": {},
- "source": [
- "Similarly, you can also add additional edge attributes from a `DataFrame` using the `add_edge_attributes` function:"
- ]
+ "source": "Similarly, you can also add additional edge attributes from a `DataFrame` using the `add_edge_attributes` function. Specially-named columns `v` and `w` of this `DataFrame` indicate the start-end of the edge respectively."
},
{
"cell_type": "code",
diff --git a/docs/tutorial/manim_tutorial.ipynb b/docs/tutorial/manim_tutorial.ipynb
index baeecd12..2f24db1a 100644
--- a/docs/tutorial/manim_tutorial.ipynb
+++ b/docs/tutorial/manim_tutorial.ipynb
@@ -114,7 +114,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
- " \r"
+ " "
]
},
{
@@ -122,7 +122,7 @@
"text/html": [
"\n",
" \n",
" "
@@ -137,7 +137,7 @@
{
"data": {
"text/plain": [
- ""
+ ""
]
},
"execution_count": 4,
@@ -162,23 +162,23 @@
"execution_count": 5,
"id": "8e80f87a",
"metadata": {
- "tags": [
- "skip-execution"
- ]
+ "tags": [
+ "skip-execution"
+ ]
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
- " \r"
+ " "
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
- "Animation saved to /tmp/tmp27x6c4lg/temporal_graph_manim.gif\n",
+ "Animation saved to /tmp/tmpp1_aikeg/temporal_graph_manim.gif\n",
"Files in temp dir: ['temporal_graph_manim.gif']\n"
]
}
@@ -219,17 +219,17 @@
"cell_type": "code",
"execution_count": 6,
"id": "26a31185",
- "metadata": {
- "tags": [
- "skip-execution"
- ]
- },
+ "metadata": {
+ "tags": [
+ "skip-execution"
+ ]
+ },
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
- " \r"
+ " "
]
},
{
@@ -237,7 +237,7 @@
"text/html": [
"\n",
" \n",
" "
@@ -252,7 +252,7 @@
{
"data": {
"text/plain": [
- ""
+ ""
]
},
"execution_count": 6,
@@ -351,7 +351,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
- " \r"
+ " "
]
},
{
@@ -359,7 +359,7 @@
"text/html": [
"\n",
"