rhiza 0.2.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/actions/setup-project/action.yml +2 -24
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/scripts/marimushka.sh +11 -1
- rhiza-0.4.0/.github/scripts/sync.sh +310 -0
- rhiza-0.4.0/.github/template.yml +16 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/workflows/deptry.yml +1 -1
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/workflows/marimo.yml +1 -1
- rhiza-0.4.0/.github/workflows/structure.yml +73 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/workflows/sync.yml +1 -1
- {rhiza-0.2.0 → rhiza-0.4.0}/Makefile +8 -2
- rhiza-0.4.0/PKG-INFO +35 -0
- rhiza-0.4.0/README.md +2 -0
- rhiza-0.4.0/book/marimo/.gitkeep +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/pyproject.toml +4 -4
- {rhiza-0.2.0/tests/test_rhiza → rhiza-0.4.0/tests}/test_cli_commands.py +3 -3
- {rhiza-0.2.0 → rhiza-0.4.0}/tests/test_rhiza/conftest.py +46 -1
- {rhiza-0.2.0 → rhiza-0.4.0}/tests/test_rhiza/test_makefile.py +36 -17
- rhiza-0.4.0/tests/test_rhiza/test_marimushka_script.py +72 -0
- rhiza-0.4.0/tests/test_rhiza/test_updatereadme_script.py +94 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/uv.lock +4 -4
- rhiza-0.2.0/.devcontainer/bootstrap.sh +0 -38
- rhiza-0.2.0/.devcontainer/devcontainer.json +0 -48
- rhiza-0.2.0/.devcontainer/startup.sh +0 -10
- rhiza-0.2.0/.github/workflows/devcontainer.yml +0 -137
- rhiza-0.2.0/.github/workflows/docker.yml +0 -63
- rhiza-0.2.0/PKG-INFO +0 -690
- rhiza-0.2.0/README.md +0 -657
- rhiza-0.2.0/assets/rhiza-logo.svg +0 -81
- rhiza-0.2.0/book/marimo/df.py +0 -35
- rhiza-0.2.0/docker/Dockerfile +0 -64
- rhiza-0.2.0/docker/Dockerfile.dockerignore +0 -17
- rhiza-0.2.0/docker/README.md +0 -31
- {rhiza-0.2.0 → rhiza-0.4.0}/.editorconfig +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/renovate.json +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/scripts/book.sh +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/scripts/bump.sh +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/scripts/customisations/build-extras.sh +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/scripts/customisations/post-release.sh +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/scripts/release.sh +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/scripts/update-readme-help.sh +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/workflows/book.yml +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/workflows/ci.yml +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/workflows/pre-commit.yml +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/workflows/release.yml +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/workflows/scripts/version_matrix.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.github/workflows/scripts/version_max.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.gitignore +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/.pre-commit-config.yaml +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/CODE_OF_CONDUCT.md +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/CONTRIBUTING.md +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/LICENSE +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/pytest.ini +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/ruff.toml +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/src/rhiza/__init__.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/src/rhiza/__main__.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/src/rhiza/cli.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/src/rhiza/commands/__init__.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/src/rhiza/commands/hello.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/src/rhiza/commands/inject.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/tests/test_rhiza/README.md +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/tests/test_rhiza/test_bump_script.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/tests/test_rhiza/test_docstrings.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/tests/test_rhiza/test_git_repo_fixture.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/tests/test_rhiza/test_readme.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/tests/test_rhiza/test_release_script.py +0 -0
- {rhiza-0.2.0 → rhiza-0.4.0}/tests/test_rhiza/test_structure.py +0 -0
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
# Action: Setup Project (composite action)
|
|
5
5
|
#
|
|
6
6
|
# Purpose: Bootstrap a Python project in GitHub Actions by:
|
|
7
|
-
# - Installing Task, uv, and uvx
|
|
8
|
-
# - Optionally rendering the repository from a Copier template for tests
|
|
7
|
+
# - Installing Task, uv, and uvx
|
|
9
8
|
# - Detecting presence of pyproject.toml and exposing it as an output
|
|
10
9
|
# - Creating a virtual environment with uv and syncing dependencies
|
|
11
10
|
#
|
|
@@ -43,28 +42,7 @@ runs:
|
|
|
43
42
|
- name: Install uv
|
|
44
43
|
uses: astral-sh/setup-uv@v7
|
|
45
44
|
with:
|
|
46
|
-
version: "0.9.
|
|
47
|
-
|
|
48
|
-
- name: Render the project
|
|
49
|
-
if: hashFiles('tests/resources/render.yml') != ''
|
|
50
|
-
shell: bash
|
|
51
|
-
run: |
|
|
52
|
-
pip install copier
|
|
53
|
-
|
|
54
|
-
# Render the current folder in-place
|
|
55
|
-
copier copy . . \
|
|
56
|
-
--data-file ./tests/resources/render.yml \
|
|
57
|
-
--force \
|
|
58
|
-
--overwrite \
|
|
59
|
-
--quiet
|
|
60
|
-
|
|
61
|
-
# Delete all remaining .jinja files
|
|
62
|
-
find . -type f -name "*.jinja" -exec rm -f {} +
|
|
63
|
-
|
|
64
|
-
# Delete all folders that still contain {{ ... }}
|
|
65
|
-
find . -depth -type d -name "*{{*}}*" -exec rm -rf {} +
|
|
66
|
-
|
|
67
|
-
ls -R
|
|
45
|
+
version: "0.9.18"
|
|
68
46
|
|
|
69
47
|
- name: Check for pyproject.toml
|
|
70
48
|
id: check_pyproject
|
|
@@ -43,11 +43,21 @@ case "$UVX_BIN" in
|
|
|
43
43
|
*) ;;
|
|
44
44
|
esac
|
|
45
45
|
|
|
46
|
+
# Resolve UV_BIN to absolute path
|
|
47
|
+
case "$UV_BIN" in
|
|
48
|
+
/*) ;;
|
|
49
|
+
*/*) UV_BIN="$CURRENT_DIR/$UV_BIN" ;;
|
|
50
|
+
*) ;;
|
|
51
|
+
esac
|
|
52
|
+
|
|
53
|
+
# Derive UV_INSTALL_DIR from UV_BIN
|
|
54
|
+
UV_INSTALL_DIR=$(dirname "$UV_BIN")
|
|
55
|
+
|
|
46
56
|
# Change to the notebook directory to ensure relative paths in notebooks work correctly
|
|
47
57
|
cd "$MARIMO_FOLDER"
|
|
48
58
|
|
|
49
59
|
# Run marimushka export
|
|
50
|
-
"$UVX_BIN" "marimushka>=0.1.9" export --notebooks "." --output "$OUTPUT_DIR" --bin-path "$
|
|
60
|
+
"$UVX_BIN" "marimushka>=0.1.9" export --notebooks "." --output "$OUTPUT_DIR" --bin-path "$UV_INSTALL_DIR"
|
|
51
61
|
|
|
52
62
|
# Ensure GitHub Pages does not process with Jekyll
|
|
53
63
|
: > "$OUTPUT_DIR/.nojekyll"
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Sync configuration files from template repository
|
|
3
|
+
# - Reads configuration from .github/template.yml
|
|
4
|
+
# - Downloads specified files from the template repository
|
|
5
|
+
# - Copies them to the current repository
|
|
6
|
+
#
|
|
7
|
+
# This script is POSIX-sh compatible and provides manual sync capability
|
|
8
|
+
# for repositories that use jebel-quant/rhiza as a template.
|
|
9
|
+
|
|
10
|
+
set -e
|
|
11
|
+
|
|
12
|
+
BLUE="\033[36m"
|
|
13
|
+
RED="\033[31m"
|
|
14
|
+
GREEN="\033[32m"
|
|
15
|
+
YELLOW="\033[33m"
|
|
16
|
+
RESET="\033[0m"
|
|
17
|
+
|
|
18
|
+
TEMPLATE_CONFIG=".github/template.yml"
|
|
19
|
+
TEMP_DIR="/tmp/rhiza-sync-$$"
|
|
20
|
+
|
|
21
|
+
show_usage() {
|
|
22
|
+
printf "Usage: %s [OPTIONS]\n\n" "$0"
|
|
23
|
+
printf "Sync configuration files from the template repository.\n\n"
|
|
24
|
+
printf "Options:\n"
|
|
25
|
+
printf " -h, --help Show this help message\n"
|
|
26
|
+
printf " --dry-run Show what would be synced without making changes\n\n"
|
|
27
|
+
printf "Configuration:\n"
|
|
28
|
+
printf " Reads from %s to determine:\n" "$TEMPLATE_CONFIG"
|
|
29
|
+
printf " - template-repository: Source repository (e.g., 'jebel-quant/rhiza')\n"
|
|
30
|
+
printf " - template-branch: Branch to sync from (e.g., 'main')\n"
|
|
31
|
+
printf " - include: Files/directories to sync\n"
|
|
32
|
+
printf " - exclude: Files/directories to skip (optional)\n\n"
|
|
33
|
+
printf "Example %s:\n" "$TEMPLATE_CONFIG"
|
|
34
|
+
printf " template-repository: \"jebel-quant/rhiza\"\n"
|
|
35
|
+
printf " template-branch: \"main\"\n"
|
|
36
|
+
printf " include: |\n"
|
|
37
|
+
printf " .github\n"
|
|
38
|
+
printf " Makefile\n"
|
|
39
|
+
printf " ruff.toml\n"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
DRY_RUN=""
|
|
43
|
+
while [ $# -gt 0 ]; do
|
|
44
|
+
case "$1" in
|
|
45
|
+
-h|--help)
|
|
46
|
+
show_usage
|
|
47
|
+
exit 0
|
|
48
|
+
;;
|
|
49
|
+
--dry-run)
|
|
50
|
+
DRY_RUN="true"
|
|
51
|
+
shift
|
|
52
|
+
;;
|
|
53
|
+
*)
|
|
54
|
+
printf "%b[ERROR] Unknown option: %s%b\n" "$RED" "$1" "$RESET"
|
|
55
|
+
show_usage
|
|
56
|
+
exit 1
|
|
57
|
+
;;
|
|
58
|
+
esac
|
|
59
|
+
done
|
|
60
|
+
|
|
61
|
+
# Check if template.yml exists
|
|
62
|
+
if [ ! -f "$TEMPLATE_CONFIG" ]; then
|
|
63
|
+
printf "%b[ERROR] Template configuration not found: %s%b\n" "$RED" "$TEMPLATE_CONFIG" "$RESET"
|
|
64
|
+
printf "\nThis repository is not configured for template syncing.\n"
|
|
65
|
+
printf "Create %s with the following content:\n\n" "$TEMPLATE_CONFIG"
|
|
66
|
+
printf " template-repository: \"jebel-quant/rhiza\"\n"
|
|
67
|
+
printf " template-branch: \"main\"\n"
|
|
68
|
+
printf " include: |\n"
|
|
69
|
+
printf " .github\n"
|
|
70
|
+
printf " Makefile\n"
|
|
71
|
+
printf " ruff.toml\n"
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Parse template.yml to extract configuration
|
|
76
|
+
# This is a simple parser that works with basic YAML structure
|
|
77
|
+
printf "%b[INFO] Reading configuration from %s...%b\n" "$BLUE" "$TEMPLATE_CONFIG" "$RESET"
|
|
78
|
+
|
|
79
|
+
TEMPLATE_REPO=""
|
|
80
|
+
TEMPLATE_BRANCH=""
|
|
81
|
+
INCLUDE_LIST=""
|
|
82
|
+
EXCLUDE_LIST=""
|
|
83
|
+
|
|
84
|
+
# Simple YAML parser
|
|
85
|
+
in_multiline=""
|
|
86
|
+
|
|
87
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
88
|
+
# Skip comments and empty lines
|
|
89
|
+
case "$line" in
|
|
90
|
+
\#*|"") continue ;;
|
|
91
|
+
esac
|
|
92
|
+
|
|
93
|
+
# Check if line starts with spaces by looking at first character
|
|
94
|
+
first_char=$(printf '%s' "$line" | cut -c1)
|
|
95
|
+
|
|
96
|
+
if [ "$first_char" = " " ] || [ "$first_char" = "$(printf '\t')" ]; then
|
|
97
|
+
# This is indented content (part of a multiline block)
|
|
98
|
+
if [ -n "$in_multiline" ]; then
|
|
99
|
+
# Remove leading spaces
|
|
100
|
+
item=$(echo "$line" | sed 's/^[[:space:]]*//')
|
|
101
|
+
if [ -n "$item" ]; then
|
|
102
|
+
if [ "$in_multiline" = "include" ]; then
|
|
103
|
+
INCLUDE_LIST="${INCLUDE_LIST}${item}
|
|
104
|
+
"
|
|
105
|
+
elif [ "$in_multiline" = "exclude" ]; then
|
|
106
|
+
EXCLUDE_LIST="${EXCLUDE_LIST}${item}
|
|
107
|
+
"
|
|
108
|
+
fi
|
|
109
|
+
fi
|
|
110
|
+
fi
|
|
111
|
+
else
|
|
112
|
+
# This is a key line (not indented)
|
|
113
|
+
case "$line" in
|
|
114
|
+
template-repository:*)
|
|
115
|
+
TEMPLATE_REPO=$(echo "$line" | sed 's/^template-repository:[[:space:]]*//' | sed 's/"//g' | sed "s/'//g")
|
|
116
|
+
in_multiline=""
|
|
117
|
+
;;
|
|
118
|
+
template-branch:*)
|
|
119
|
+
TEMPLATE_BRANCH=$(echo "$line" | sed 's/^template-branch:[[:space:]]*//' | sed 's/"//g' | sed "s/'//g")
|
|
120
|
+
in_multiline=""
|
|
121
|
+
;;
|
|
122
|
+
include:*)
|
|
123
|
+
in_multiline="include"
|
|
124
|
+
;;
|
|
125
|
+
exclude:*)
|
|
126
|
+
in_multiline="exclude"
|
|
127
|
+
;;
|
|
128
|
+
esac
|
|
129
|
+
fi
|
|
130
|
+
done < "$TEMPLATE_CONFIG"
|
|
131
|
+
|
|
132
|
+
# Validate required fields
|
|
133
|
+
if [ -z "$TEMPLATE_REPO" ]; then
|
|
134
|
+
printf "%b[ERROR] template-repository not found in %s%b\n" "$RED" "$TEMPLATE_CONFIG" "$RESET"
|
|
135
|
+
exit 1
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
if [ -z "$TEMPLATE_BRANCH" ]; then
|
|
139
|
+
printf "%b[WARN] template-branch not specified, using 'main'%b\n" "$YELLOW" "$RESET"
|
|
140
|
+
TEMPLATE_BRANCH="main"
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
if [ -z "$INCLUDE_LIST" ]; then
|
|
144
|
+
printf "%b[ERROR] include list is empty in %s%b\n" "$RED" "$TEMPLATE_CONFIG" "$RESET"
|
|
145
|
+
exit 1
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
printf "%b[INFO] Template repository: %s%b\n" "$GREEN" "$TEMPLATE_REPO" "$RESET"
|
|
149
|
+
printf "%b[INFO] Template branch: %s%b\n" "$GREEN" "$TEMPLATE_BRANCH" "$RESET"
|
|
150
|
+
printf "%b[INFO] Files to sync:%b\n" "$GREEN" "$RESET"
|
|
151
|
+
echo "$INCLUDE_LIST" | while IFS= read -r item; do
|
|
152
|
+
[ -n "$item" ] && printf " - %s\n" "$item"
|
|
153
|
+
done || true
|
|
154
|
+
|
|
155
|
+
if [ -n "$EXCLUDE_LIST" ]; then
|
|
156
|
+
printf "%b[INFO] Files to exclude:%b\n" "$YELLOW" "$RESET"
|
|
157
|
+
echo "$EXCLUDE_LIST" | while IFS= read -r item; do
|
|
158
|
+
[ -n "$item" ] && printf " - %s\n" "$item"
|
|
159
|
+
done || true
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
if [ -n "$DRY_RUN" ]; then
|
|
163
|
+
printf "\n%b[DRY RUN] No changes will be made%b\n" "$YELLOW" "$RESET"
|
|
164
|
+
exit 0
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# Create temporary directory
|
|
168
|
+
mkdir -p "$TEMP_DIR"
|
|
169
|
+
trap 'rm -rf "$TEMP_DIR"' EXIT INT TERM
|
|
170
|
+
|
|
171
|
+
# Backup this script to avoid being overwritten during sync
|
|
172
|
+
SELF_SCRIPT=".github/scripts/sync.sh"
|
|
173
|
+
if [ -f "$SELF_SCRIPT" ]; then
|
|
174
|
+
cp "$SELF_SCRIPT" "$TEMP_DIR/sync.sh.bak"
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# Clone the template repository
|
|
178
|
+
printf "\n%b[INFO] Cloning template repository...%b\n" "$BLUE" "$RESET"
|
|
179
|
+
REPO_URL="https://github.com/${TEMPLATE_REPO}.git"
|
|
180
|
+
|
|
181
|
+
if ! git clone --depth 1 --branch "$TEMPLATE_BRANCH" "$REPO_URL" "$TEMP_DIR/template" 2>/dev/null; then
|
|
182
|
+
printf "%b[ERROR] Failed to clone template repository from %s%b\n" "$RED" "$REPO_URL" "$RESET"
|
|
183
|
+
exit 1
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
# Function to check if a file path should be excluded
|
|
187
|
+
is_file_excluded() {
|
|
188
|
+
file_path="$1"
|
|
189
|
+
if [ -z "$EXCLUDE_LIST" ]; then
|
|
190
|
+
return 1 # Not excluded (false)
|
|
191
|
+
fi
|
|
192
|
+
|
|
193
|
+
while IFS= read -r exclude_item || [ -n "$exclude_item" ]; do
|
|
194
|
+
[ -z "$exclude_item" ] && continue
|
|
195
|
+
if [ "$file_path" = "$exclude_item" ]; then
|
|
196
|
+
return 0 # Is excluded (true)
|
|
197
|
+
fi
|
|
198
|
+
done <<EOF_EXCLUDE_CHECK
|
|
199
|
+
$EXCLUDE_LIST
|
|
200
|
+
EOF_EXCLUDE_CHECK
|
|
201
|
+
|
|
202
|
+
return 1 # Not excluded (false)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
# Copy files from template to current directory
|
|
206
|
+
printf "%b[INFO] Syncing files...%b\n" "$BLUE" "$RESET"
|
|
207
|
+
|
|
208
|
+
synced_count=0
|
|
209
|
+
skipped_count=0
|
|
210
|
+
# Track whether .github (containing this script) was synced and whether a direct self update was requested
|
|
211
|
+
synced_dotgithub="false"
|
|
212
|
+
deferred_self_update="false"
|
|
213
|
+
|
|
214
|
+
# Use here-document instead of pipeline to avoid subshell
|
|
215
|
+
while IFS= read -r item || [ -n "$item" ]; do
|
|
216
|
+
[ -z "$item" ] && continue
|
|
217
|
+
|
|
218
|
+
# Check if this item is in the exclude list
|
|
219
|
+
if is_file_excluded "$item"; then
|
|
220
|
+
printf " %b[SKIP]%b %s (excluded)\n" "$YELLOW" "$RESET" "$item"
|
|
221
|
+
skipped_count=$((skipped_count + 1))
|
|
222
|
+
continue
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
# Defer updating this script to the very end to avoid mid-run overwrite
|
|
226
|
+
if [ "$item" = ".github/scripts/sync.sh" ]; then
|
|
227
|
+
deferred_self_update="true"
|
|
228
|
+
printf " %b[DEFER]%b %s (will update at end)\n" "$YELLOW" "$RESET" "$item"
|
|
229
|
+
continue
|
|
230
|
+
fi
|
|
231
|
+
|
|
232
|
+
src_path="$TEMP_DIR/template/$item"
|
|
233
|
+
dest_path="./$item"
|
|
234
|
+
|
|
235
|
+
if [ -e "$src_path" ]; then
|
|
236
|
+
# Create parent directory if needed
|
|
237
|
+
dest_dir=$(dirname "$dest_path")
|
|
238
|
+
mkdir -p "$dest_dir"
|
|
239
|
+
|
|
240
|
+
# Copy the file or directory
|
|
241
|
+
if [ -d "$src_path" ]; then
|
|
242
|
+
# Ensure destination directory exists
|
|
243
|
+
mkdir -p "$dest_path"
|
|
244
|
+
# Copy contents of the source directory into the destination directory
|
|
245
|
+
# to avoid nesting (e.g., .github/.github or tests/tests)
|
|
246
|
+
cp -R "$src_path"/. "$dest_path"/
|
|
247
|
+
# Mark if we synced the .github directory so we can safely update sync.sh at the end
|
|
248
|
+
if [ "$item" = ".github" ]; then
|
|
249
|
+
synced_dotgithub="true"
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
# Remove excluded files from the copied directory
|
|
253
|
+
if [ -n "$EXCLUDE_LIST" ]; then
|
|
254
|
+
while IFS= read -r exclude_item || [ -n "$exclude_item" ]; do
|
|
255
|
+
[ -z "$exclude_item" ] && continue
|
|
256
|
+
# Check if the excluded item is a child of the current item
|
|
257
|
+
# e.g., if item=".github" and exclude_item=".github/workflows/docker.yml"
|
|
258
|
+
case "$exclude_item" in
|
|
259
|
+
"$item"/*)
|
|
260
|
+
# This is a nested file that should be excluded
|
|
261
|
+
excluded_file_path="./$exclude_item"
|
|
262
|
+
if [ -e "$excluded_file_path" ]; then
|
|
263
|
+
rm -rf "$excluded_file_path"
|
|
264
|
+
printf " %b[EXCLUDE]%b %s (removed from synced directory)\n" "$YELLOW" "$RESET" "$exclude_item"
|
|
265
|
+
fi
|
|
266
|
+
;;
|
|
267
|
+
esac
|
|
268
|
+
done <<EOF_EXCLUDE_NESTED
|
|
269
|
+
$EXCLUDE_LIST
|
|
270
|
+
EOF_EXCLUDE_NESTED
|
|
271
|
+
fi
|
|
272
|
+
|
|
273
|
+
# If we just synced the .github directory, restore this script immediately to avoid mid-run overwrite issues
|
|
274
|
+
if [ "$item" = ".github" ] && [ -f "$TEMP_DIR/sync.sh.bak" ]; then
|
|
275
|
+
cp "$TEMP_DIR/sync.sh.bak" "$SELF_SCRIPT"
|
|
276
|
+
fi
|
|
277
|
+
printf " %b[SYNC]%b %s (directory contents)\n" "$GREEN" "$RESET" "$item"
|
|
278
|
+
else
|
|
279
|
+
cp "$src_path" "$dest_path"
|
|
280
|
+
printf " %b[SYNC]%b %s\n" "$GREEN" "$RESET" "$item"
|
|
281
|
+
fi
|
|
282
|
+
synced_count=$((synced_count + 1))
|
|
283
|
+
else
|
|
284
|
+
printf " %b[WARN]%b %s (not found in template)\n" "$YELLOW" "$RESET" "$item"
|
|
285
|
+
skipped_count=$((skipped_count + 1))
|
|
286
|
+
fi
|
|
287
|
+
done <<EOF_INCLUDE
|
|
288
|
+
$INCLUDE_LIST
|
|
289
|
+
EOF_INCLUDE
|
|
290
|
+
|
|
291
|
+
# Finalize self-update of sync.sh if applicable
|
|
292
|
+
TEMPLATE_SELF_SH="$TEMP_DIR/template/.github/scripts/sync.sh"
|
|
293
|
+
if [ -f "$TEMPLATE_SELF_SH" ] && { [ "$deferred_self_update" = "true" ] || [ "$synced_dotgithub" = "true" ]; }; then
|
|
294
|
+
if is_file_excluded ".github/scripts/sync.sh"; then
|
|
295
|
+
printf " %b[SKIP]%b .github/scripts/sync.sh (excluded from final update)\n" "$YELLOW" "$RESET"
|
|
296
|
+
else
|
|
297
|
+
cp "$TEMPLATE_SELF_SH" "$SELF_SCRIPT"
|
|
298
|
+
chmod +x "$SELF_SCRIPT" 2>/dev/null || true
|
|
299
|
+
printf " %b[SYNC]%b .github/scripts/sync.sh (finalized)\n" "$GREEN" "$RESET"
|
|
300
|
+
fi
|
|
301
|
+
fi
|
|
302
|
+
|
|
303
|
+
printf "\n%b[INFO] Sync complete!%b\n" "$GREEN" "$RESET"
|
|
304
|
+
printf " Synced: %d files/directories\n" "$synced_count"
|
|
305
|
+
if [ "$skipped_count" -gt 0 ]; then
|
|
306
|
+
printf " Skipped: %d files/directories\n" "$skipped_count"
|
|
307
|
+
fi
|
|
308
|
+
|
|
309
|
+
printf "\n%b[INFO] Review the changes with: git status%b\n" "$BLUE" "$RESET"
|
|
310
|
+
printf "%b[INFO] Commit the changes with: git add . && git commit -m 'chore: sync template files'%b\n" "$BLUE" "$RESET"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
template-repository: "jebel-quant/rhiza"
|
|
2
|
+
template-branch: "main"
|
|
3
|
+
include:
|
|
4
|
+
- .github
|
|
5
|
+
- tests
|
|
6
|
+
- .editorconfig
|
|
7
|
+
- .gitignore
|
|
8
|
+
- .pre-commit-config.yaml
|
|
9
|
+
- CODE_OF_CONDUCT.md
|
|
10
|
+
- CONTRIBUTING.md
|
|
11
|
+
- Makefile
|
|
12
|
+
- ruff.toml
|
|
13
|
+
- pytest.ini
|
|
14
|
+
exclude:
|
|
15
|
+
- .github/workflows/docker.yml
|
|
16
|
+
- .github/workflows/devcontainer.yml
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# This file is part of the jebel-quant/rhiza repository
|
|
2
|
+
# (https://github.com/jebel-quant/rhiza).
|
|
3
|
+
#
|
|
4
|
+
# GitHub Actions workflow: repository structure advisory checks
|
|
5
|
+
# Purpose: Soft-check the presence of common scaffolding (src/, tests/, and key dotfiles)
|
|
6
|
+
# and print WARN messages if something is missing. This workflow is advisory:
|
|
7
|
+
# it never fails the job based on these checks; it only surfaces helpful hints
|
|
8
|
+
# for template consumers.
|
|
9
|
+
#
|
|
10
|
+
# Triggers: on push and pull requests targeting main/master.
|
|
11
|
+
# Permissions: read-only; no writes or tokens required. LFS enabled to support
|
|
12
|
+
# repositories that track large files.
|
|
13
|
+
# Notes: The shell steps use printf with optional color variables (e.g., YELLOW,
|
|
14
|
+
# RESET). If these env vars are unset in the runner, the parameter expansion
|
|
15
|
+
# defaults ensure plain text output without ANSI colors.
|
|
16
|
+
name: "STRUCTURE"
|
|
17
|
+
|
|
18
|
+
# Minimal read permission is sufficient; the workflow does not modify the repo
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
|
|
22
|
+
# Run on pushes and pull requests to the default branches
|
|
23
|
+
on:
|
|
24
|
+
push:
|
|
25
|
+
pull_request:
|
|
26
|
+
branches: [ main, master ]
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
# Single job that performs presence checks and emits WARN lines (warn-only)
|
|
30
|
+
structure_check:
|
|
31
|
+
runs-on: "ubuntu-latest"
|
|
32
|
+
|
|
33
|
+
permissions:
|
|
34
|
+
contents: read
|
|
35
|
+
|
|
36
|
+
steps:
|
|
37
|
+
# Check out the repository code (with Git LFS files, if any)
|
|
38
|
+
- uses: actions/checkout@v6
|
|
39
|
+
with:
|
|
40
|
+
lfs: true
|
|
41
|
+
|
|
42
|
+
# Check there is a src folder
|
|
43
|
+
- name: Check src folder exists
|
|
44
|
+
run: |
|
|
45
|
+
if [ ! -d "src" ]; then
|
|
46
|
+
printf "${YELLOW:-}[WARN] No src folder found, skipping structure check${RESET:-}\n"
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Check there is a tests folder
|
|
50
|
+
- name: Check tests folder exists
|
|
51
|
+
run: |
|
|
52
|
+
if [ ! -d "tests" ]; then
|
|
53
|
+
printf "${YELLOW:-}[WARN] No tests folder found, skipping structure check${RESET:-}\n"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Check there is a .editorconfig, .gitignore, .pre-commit-config.yaml and Makefile file
|
|
57
|
+
- name: Check .editorconfig and .gitignore files exist
|
|
58
|
+
run: |
|
|
59
|
+
if [ ! -f ".editorconfig" ]; then
|
|
60
|
+
printf "${YELLOW:-}[WARN] No .editorconfig file found, skipping structure check${RESET:-}\n"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
if [ ! -f ".gitignore" ]; then
|
|
64
|
+
printf "${YELLOW:-}[WARN] No .gitignore file found, skipping structure check${RESET:-}\n"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
if [ ! -f ".pre-commit-config.yaml" ]; then
|
|
68
|
+
printf "${YELLOW:-}[WARN] No .pre-commit-config file found, skipping structure check${RESET:-}\n"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
if [ ! -f "Makefile" ]; then
|
|
72
|
+
printf "${YELLOW:-}[WARN] No Makefile found, skipping structure check${RESET:-}\n"
|
|
73
|
+
fi
|
|
@@ -30,6 +30,7 @@ BOOK_SUBTITLE := Generated by minibook
|
|
|
30
30
|
SCRIPTS_FOLDER := .github/scripts
|
|
31
31
|
CUSTOM_SCRIPTS_FOLDER := .github/scripts/customisations
|
|
32
32
|
PDOC_TEMPLATE_DIR := book/pdoc-templates
|
|
33
|
+
BOOK_TEMPLATE := book/minibook-templates/custom.html.jinja2
|
|
33
34
|
DOCFORMAT :=
|
|
34
35
|
|
|
35
36
|
export UV_NO_MODIFY_PATH := 1
|
|
@@ -110,7 +111,7 @@ marimo: install ## fire up Marimo server
|
|
|
110
111
|
@if [ ! -d "${MARIMO_FOLDER}" ]; then \
|
|
111
112
|
printf " ${YELLOW}[WARN] Marimo folder '${MARIMO_FOLDER}' not found, skipping start${RESET}\n"; \
|
|
112
113
|
else \
|
|
113
|
-
${UV_BIN} run --with marimo marimo edit "${MARIMO_FOLDER}"; \
|
|
114
|
+
${UV_BIN} run --with marimo marimo edit --no-token --headless "${MARIMO_FOLDER}"; \
|
|
114
115
|
fi
|
|
115
116
|
|
|
116
117
|
marimushka: install-uv ## export Marimo notebooks to HTML
|
|
@@ -162,7 +163,12 @@ docs: install ## create documentation with pdoc
|
|
|
162
163
|
book: test docs marimushka ## compile the companion book
|
|
163
164
|
@${UV_BIN} pip install marimo
|
|
164
165
|
@/bin/sh "${SCRIPTS_FOLDER}/book.sh"
|
|
165
|
-
|
|
166
|
+
@TEMPLATE_ARG=""; \
|
|
167
|
+
if [ -f "${BOOK_TEMPLATE}" ]; then \
|
|
168
|
+
TEMPLATE_ARG="--template ${BOOK_TEMPLATE}"; \
|
|
169
|
+
printf "${BLUE}[INFO] Using book template ${BOOK_TEMPLATE}${RESET}\n"; \
|
|
170
|
+
fi; \
|
|
171
|
+
${UVX_BIN} minibook --title "${BOOK_TITLE}" --subtitle "${BOOK_SUBTITLE}" $$TEMPLATE_ARG --links "$$(python3 -c 'import json,sys; print(json.dumps(json.load(open("_book/links.json"))))')" --output "_book"
|
|
166
172
|
@touch "_book/.nojekyll"
|
|
167
173
|
|
|
168
174
|
fmt: install-uv ## check the pre-commit hooks and the linting
|
rhiza-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rhiza
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Reusable configuration templates for modern Python projects
|
|
5
|
+
Project-URL: Homepage, https://github.com/jebel-quant/rhiza-cli
|
|
6
|
+
Project-URL: Repository, https://github.com/jebel-quant/rhiza-cli
|
|
7
|
+
Project-URL: Issues, https://github.com/jebel-quant/rhiza/issues-cli
|
|
8
|
+
Author: Thomas Schmelzer
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ci,configuration,ruff,taskfile,templates
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: loguru>=0.7.3
|
|
23
|
+
Requires-Dist: pyyaml==6.0.3
|
|
24
|
+
Requires-Dist: typer>=0.20.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: marimo==0.18.4; extra == 'dev'
|
|
27
|
+
Requires-Dist: pdoc>=16.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pre-commit==4.5.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-html>=4.1.1; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest==9.0.2; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# rhiza-cli
|
|
35
|
+
Command line interface for Rhiza
|
rhiza-0.4.0/README.md
ADDED
|
File without changes
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rhiza"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "Reusable configuration templates for modern Python projects"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -32,9 +32,9 @@ dependencies = [
|
|
|
32
32
|
]
|
|
33
33
|
|
|
34
34
|
[project.urls]
|
|
35
|
-
Homepage = "https://github.com/jebel-quant/rhiza"
|
|
36
|
-
Repository = "https://github.com/jebel-quant/rhiza"
|
|
37
|
-
Issues = "https://github.com/jebel-quant/rhiza/issues"
|
|
35
|
+
Homepage = "https://github.com/jebel-quant/rhiza-cli"
|
|
36
|
+
Repository = "https://github.com/jebel-quant/rhiza-cli"
|
|
37
|
+
Issues = "https://github.com/jebel-quant/rhiza/issues-cli"
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
[project.optional-dependencies]
|
|
@@ -460,7 +460,7 @@ class TestMaterializeCommand:
|
|
|
460
460
|
runner = CliRunner()
|
|
461
461
|
with runner.isolated_filesystem():
|
|
462
462
|
# Create a dummy directory to pass validation
|
|
463
|
-
Path("
|
|
463
|
+
Path("test_rhiza").mkdir(exist_ok=True)
|
|
464
464
|
runner.invoke(cli.app, ["materialize"])
|
|
465
465
|
# Note: the command will fail because . is not a git repo, but we're mocking inject
|
|
466
466
|
# Check that inject was called (even if validation fails in typer)
|
|
@@ -470,7 +470,7 @@ class TestMaterializeCommand:
|
|
|
470
470
|
"""Test materialize command with custom branch option."""
|
|
471
471
|
runner = CliRunner()
|
|
472
472
|
with runner.isolated_filesystem():
|
|
473
|
-
Path("
|
|
473
|
+
Path("test_rhiza").mkdir(exist_ok=True)
|
|
474
474
|
runner.invoke(cli.app, ["materialize", "--branch", "dev"])
|
|
475
475
|
|
|
476
476
|
@patch("rhiza.cli.inject_cmd")
|
|
@@ -478,5 +478,5 @@ class TestMaterializeCommand:
|
|
|
478
478
|
"""Test materialize command with force option."""
|
|
479
479
|
runner = CliRunner()
|
|
480
480
|
with runner.isolated_filesystem():
|
|
481
|
-
Path("
|
|
481
|
+
Path("test_rhiza").mkdir(exist_ok=True)
|
|
482
482
|
runner.invoke(cli.app, ["materialize", "--force"])
|