rhiza 0.3.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.
Files changed (66) hide show
  1. {rhiza-0.3.0 → rhiza-0.4.0}/.github/actions/setup-project/action.yml +2 -24
  2. rhiza-0.4.0/.github/scripts/sync.sh +310 -0
  3. rhiza-0.4.0/.github/template.yml +16 -0
  4. {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/deptry.yml +1 -1
  5. {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/marimo.yml +1 -1
  6. rhiza-0.4.0/.github/workflows/structure.yml +73 -0
  7. {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/sync.yml +1 -1
  8. rhiza-0.4.0/PKG-INFO +35 -0
  9. rhiza-0.4.0/README.md +2 -0
  10. {rhiza-0.3.0 → rhiza-0.4.0}/pyproject.toml +17 -5
  11. rhiza-0.4.0/src/rhiza/__init__.py +5 -0
  12. rhiza-0.4.0/src/rhiza/__main__.py +10 -0
  13. rhiza-0.4.0/src/rhiza/cli.py +47 -0
  14. rhiza-0.4.0/src/rhiza/commands/__init__.py +5 -0
  15. rhiza-0.4.0/src/rhiza/commands/hello.py +9 -0
  16. rhiza-0.4.0/src/rhiza/commands/inject.py +160 -0
  17. rhiza-0.4.0/tests/test_cli_commands.py +482 -0
  18. {rhiza-0.3.0 → rhiza-0.4.0}/uv.lock +92 -4
  19. rhiza-0.3.0/.devcontainer/bootstrap.sh +0 -38
  20. rhiza-0.3.0/.devcontainer/devcontainer.json +0 -48
  21. rhiza-0.3.0/.github/workflows/devcontainer.yml +0 -137
  22. rhiza-0.3.0/.github/workflows/docker.yml +0 -63
  23. rhiza-0.3.0/PKG-INFO +0 -709
  24. rhiza-0.3.0/README.md +0 -679
  25. rhiza-0.3.0/assets/rhiza-logo.svg +0 -81
  26. rhiza-0.3.0/book/marimo/df.py +0 -37
  27. rhiza-0.3.0/book/minibook-templates/custom.html.jinja2 +0 -210
  28. rhiza-0.3.0/book/pdoc-templates/module.html.jinja2 +0 -19
  29. rhiza-0.3.0/docker/Dockerfile +0 -64
  30. rhiza-0.3.0/docker/Dockerfile.dockerignore +0 -17
  31. rhiza-0.3.0/docker/README.md +0 -31
  32. {rhiza-0.3.0 → rhiza-0.4.0}/.editorconfig +0 -0
  33. {rhiza-0.3.0 → rhiza-0.4.0}/.github/renovate.json +0 -0
  34. {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/book.sh +0 -0
  35. {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/bump.sh +0 -0
  36. {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/customisations/build-extras.sh +0 -0
  37. {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/customisations/post-release.sh +0 -0
  38. {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/marimushka.sh +0 -0
  39. {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/release.sh +0 -0
  40. {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/update-readme-help.sh +0 -0
  41. {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/book.yml +0 -0
  42. {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/ci.yml +0 -0
  43. {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/pre-commit.yml +0 -0
  44. {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/release.yml +0 -0
  45. {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/scripts/version_matrix.py +0 -0
  46. {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/scripts/version_max.py +0 -0
  47. {rhiza-0.3.0 → rhiza-0.4.0}/.gitignore +0 -0
  48. {rhiza-0.3.0 → rhiza-0.4.0}/.pre-commit-config.yaml +0 -0
  49. {rhiza-0.3.0 → rhiza-0.4.0}/CODE_OF_CONDUCT.md +0 -0
  50. {rhiza-0.3.0 → rhiza-0.4.0}/CONTRIBUTING.md +0 -0
  51. {rhiza-0.3.0 → rhiza-0.4.0}/LICENSE +0 -0
  52. {rhiza-0.3.0 → rhiza-0.4.0}/Makefile +0 -0
  53. {rhiza-0.3.0/src/rhiza → rhiza-0.4.0/book/marimo}/.gitkeep +0 -0
  54. {rhiza-0.3.0 → rhiza-0.4.0}/pytest.ini +0 -0
  55. {rhiza-0.3.0 → rhiza-0.4.0}/ruff.toml +0 -0
  56. {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/README.md +0 -0
  57. {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/conftest.py +0 -0
  58. {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_bump_script.py +0 -0
  59. {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_docstrings.py +0 -0
  60. {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_git_repo_fixture.py +0 -0
  61. {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_makefile.py +0 -0
  62. {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_marimushka_script.py +0 -0
  63. {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_readme.py +0 -0
  64. {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_release_script.py +0 -0
  65. {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_structure.py +0 -0
  66. {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_updatereadme_script.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 into a local ./bin directory
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.17"
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
@@ -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
@@ -26,7 +26,7 @@ jobs:
26
26
  name: Check dependencies with deptry
27
27
  runs-on: ubuntu-latest
28
28
  container:
29
- image: ghcr.io/astral-sh/uv:0.9.17-python3.12-trixie
29
+ image: ghcr.io/astral-sh/uv:0.9.18-python3.12-trixie
30
30
 
31
31
  steps:
32
32
  - uses: actions/checkout@v6
@@ -79,7 +79,7 @@ jobs:
79
79
  - name: Install uv
80
80
  uses: astral-sh/setup-uv@v7
81
81
  with:
82
- version: "0.9.17"
82
+ version: "0.9.18"
83
83
 
84
84
  # Execute the notebook with the appropriate runner based on its content
85
85
  - name: Run notebook
@@ -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
@@ -32,7 +32,7 @@ jobs:
32
32
  steps:
33
33
  - name: Sync Template
34
34
  id: sync
35
- uses: jebel-quant/sync_template@v0.4.2
35
+ uses: jebel-quant/sync_template@v0.4.3
36
36
  with:
37
37
  token: ${{ secrets.PAT_TOKEN }}
38
38
  source: ".github/template.yml"
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
@@ -0,0 +1,2 @@
1
+ # rhiza-cli
2
+ Command line interface for Rhiza
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "rhiza"
7
- version = "0.3.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"
@@ -12,7 +12,7 @@ license = { text = "MIT" }
12
12
  authors = [
13
13
  { name = "Thomas Schmelzer" }
14
14
  ]
15
- keywords = ["templates", "configuration", "ci", "ruff"]
15
+ keywords = ["templates", "configuration", "taskfile", "ci", "ruff"]
16
16
  classifiers = [
17
17
  "Programming Language :: Python :: 3",
18
18
  "Programming Language :: Python :: 3 :: Only",
@@ -25,10 +25,16 @@ classifiers = [
25
25
  "Topic :: Software Development :: Build Tools",
26
26
  ]
27
27
 
28
+ dependencies = [
29
+ "loguru>=0.7.3",
30
+ "typer>=0.20.0",
31
+ "PyYAML==6.0.3"
32
+ ]
33
+
28
34
  [project.urls]
29
- Homepage = "https://github.com/jebel-quant/rhiza"
30
- Repository = "https://github.com/jebel-quant/rhiza"
31
- 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"
32
38
 
33
39
 
34
40
  [project.optional-dependencies]
@@ -49,5 +55,11 @@ packages = ["src/rhiza"]
49
55
  # see https://deptry.com/usage/#pep-621-dev-dependency-groups
50
56
  pep621_dev_dependency_groups = ["dev"]
51
57
 
58
+ [tool.deptry.package_module_name_map]
59
+ PyYAML = "yaml"
60
+
52
61
  [tool.marimo.runtime]
53
62
  pythonpath = ["src"]
63
+
64
+ [project.scripts]
65
+ rhiza = "rhiza.__main__:app"
@@ -0,0 +1,5 @@
1
+ """Utility tools and command-line helpers for the Rhiza project.
2
+
3
+ This package groups small, user-facing utilities that can be invoked from
4
+ the command line or other automation scripts.
5
+ """
@@ -0,0 +1,10 @@
1
+ """Rhiza module entry point.
2
+
3
+ This module allows running the Rhiza CLI with `python -m rhiza` by
4
+ delegating execution to the Typer application defined in `rhiza.cli`.
5
+ """
6
+
7
+ from rhiza.cli import app
8
+
9
+ if __name__ == "__main__":
10
+ app()
@@ -0,0 +1,47 @@
1
+ """Rhiza command-line interface (CLI).
2
+
3
+ This module defines the Typer application entry points exposed by Rhiza.
4
+ Commands are thin wrappers around implementations in `rhiza.commands.*`.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ import typer
10
+
11
+ from rhiza.commands.hello import hello as hello_cmd
12
+ from rhiza.commands.inject import inject as inject_cmd
13
+
14
+ app = typer.Typer(help="rhiza — configuration materialization tools")
15
+
16
+
17
+ @app.command()
18
+ def hello():
19
+ """Sanity check command."""
20
+ hello_cmd()
21
+
22
+
23
+ @app.command()
24
+ def materialize(
25
+ target: Path = typer.Argument(
26
+ default=Path("."), # default to current directory
27
+ exists=True,
28
+ file_okay=False,
29
+ dir_okay=True,
30
+ help="Target git repository (defaults to current directory)",
31
+ ),
32
+ branch: str = typer.Option("main", "--branch", "-b", help="Rhiza branch to use"),
33
+ force: bool = typer.Option(False, "--force", "-y", help="Overwrite existing files"),
34
+ ):
35
+ """Inject Rhiza configuration into a target repository.
36
+
37
+ Parameters
38
+ ----------
39
+ target:
40
+ Path to the target Git repository directory. Defaults to the
41
+ current working directory.
42
+ branch:
43
+ Name of the Rhiza branch to use when sourcing templates.
44
+ force:
45
+ If True, overwrite existing files without prompting.
46
+ """
47
+ inject_cmd(target, branch, force)
@@ -0,0 +1,5 @@
1
+ """Command implementations for the Rhiza CLI.
2
+
3
+ This package contains the functions that back Typer commands exposed by
4
+ `rhiza.cli`, such as `hello` and `inject`.
5
+ """
@@ -0,0 +1,9 @@
1
+ """Small demo CLI entrypoint for Rhiza tools.
2
+
3
+ This module provides a minimal example command that prints a greeting.
4
+ """
5
+
6
+
7
+ def hello():
8
+ """Print a friendly greeting from Rhiza."""
9
+ print("Hello from Rhiza!")