zabob-houdini 0.1.3__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.
- zabob_houdini-0.1.3/.env.example.linux +19 -0
- zabob_houdini-0.1.3/.env.example.macos +18 -0
- zabob_houdini-0.1.3/.env.example.windows +19 -0
- zabob_houdini-0.1.3/.flake8 +3 -0
- zabob_houdini-0.1.3/.gitattributes +69 -0
- zabob_houdini-0.1.3/.github/copilot-instructions.md +171 -0
- zabob_houdini-0.1.3/.github/workflows/publish.yml +197 -0
- zabob_houdini-0.1.3/.github/workflows/test.yml +118 -0
- zabob_houdini-0.1.3/.gitignore +119 -0
- zabob_houdini-0.1.3/.markdownlint.json +10 -0
- zabob_houdini-0.1.3/.python-version +1 -0
- zabob_houdini-0.1.3/.python-version-houdini +1 -0
- zabob_houdini-0.1.3/.vscode/extensions.json +11 -0
- zabob_houdini-0.1.3/.vscode/project-dictionary.txt +98 -0
- zabob_houdini-0.1.3/.vscode/settings.json.example +51 -0
- zabob_houdini-0.1.3/.vscode/setup-vscode.sh +69 -0
- zabob_houdini-0.1.3/API.md +955 -0
- zabob_houdini-0.1.3/CHANGELOG.md +95 -0
- zabob_houdini-0.1.3/COMMAND.md +380 -0
- zabob_houdini-0.1.3/DEVELOPMENT.md +459 -0
- zabob_houdini-0.1.3/LICENSE +21 -0
- zabob_houdini-0.1.3/PKG-INFO +140 -0
- zabob_houdini-0.1.3/README.md +109 -0
- zabob_houdini-0.1.3/TODO.md +51 -0
- zabob_houdini-0.1.3/ZABOB.md +87 -0
- zabob_houdini-0.1.3/cspell.json +47 -0
- zabob_houdini-0.1.3/docs/PYPI_SETUP.md +132 -0
- zabob_houdini-0.1.3/docs/images/psd/zabob-banner.psd +0 -0
- zabob_houdini-0.1.3/docs/images/psd/zabob.psd +0 -0
- zabob_houdini-0.1.3/docs/images/zabob-banner.jpg +3 -0
- zabob_houdini-0.1.3/docs/images/zabob-holodeck.jpg +3 -0
- zabob_houdini-0.1.3/docs/images/zabob-neutral-bg.jpg +3 -0
- zabob_houdini-0.1.3/docs/images/zabob.jpg +3 -0
- zabob_houdini-0.1.3/examples/chain_demo.py +95 -0
- zabob_houdini-0.1.3/examples/dependency_tracking_demo.py +89 -0
- zabob_houdini-0.1.3/examples/diamond_chain_demo.py +212 -0
- zabob_houdini-0.1.3/examples/enhanced_node_context_demo.py +83 -0
- zabob_houdini-0.1.3/examples/enhanced_typing_demo.py +46 -0
- zabob_houdini-0.1.3/examples/hython_bridge_demo.py +19 -0
- zabob_houdini-0.1.3/examples/modern_types_demo.py +34 -0
- zabob_houdini-0.1.3/examples/node_context_chain_demo.py +77 -0
- zabob_houdini-0.1.3/examples/node_context_demo.py +64 -0
- zabob_houdini-0.1.3/examples/parameterized_diamond_demo.py +61 -0
- zabob_houdini-0.1.3/examples/simple_diamond_demo.py +56 -0
- zabob_houdini-0.1.3/examples/type_narrowing_demo.py +112 -0
- zabob_houdini-0.1.3/package-lock.json +1152 -0
- zabob_houdini-0.1.3/package.json +13 -0
- zabob_houdini-0.1.3/pyproject.toml +80 -0
- zabob_houdini-0.1.3/release.sh +238 -0
- zabob_houdini-0.1.3/src/zabob_houdini/__init__.py +92 -0
- zabob_houdini-0.1.3/src/zabob_houdini/__main__.py +102 -0
- zabob_houdini-0.1.3/src/zabob_houdini/__version__.py +15 -0
- zabob_houdini-0.1.3/src/zabob_houdini/cli.py +310 -0
- zabob_houdini-0.1.3/src/zabob_houdini/core.py +1343 -0
- zabob_houdini-0.1.3/src/zabob_houdini/houdini_bridge.py +285 -0
- zabob_houdini-0.1.3/src/zabob_houdini/houdini_config.py +86 -0
- zabob_houdini-0.1.3/src/zabob_houdini/houdini_functions.py +171 -0
- zabob_houdini-0.1.3/src/zabob_houdini/houdini_info.py +433 -0
- zabob_houdini-0.1.3/src/zabob_houdini/houdini_test_functions.py +1915 -0
- zabob_houdini-0.1.3/src/zabob_houdini/houdini_versions.py +771 -0
- zabob_houdini-0.1.3/src/zabob_houdini/package_installer.py +174 -0
- zabob_houdini-0.1.3/src/zabob_houdini/utils.py +61 -0
- zabob_houdini-0.1.3/stubs/README.md +77 -0
- zabob_houdini-0.1.3/stubs/TYPE_SAFETY.md +146 -0
- zabob_houdini-0.1.3/stubs/hou.pyi +1107 -0
- zabob_houdini-0.1.3/test.sh +70 -0
- zabob_houdini-0.1.3/tests/conftest.py +196 -0
- zabob_houdini-0.1.3/tests/test_chain_positional_copy.py +56 -0
- zabob_houdini-0.1.3/tests/test_core_caching.py +237 -0
- zabob_houdini-0.1.3/tests/test_dependency_tracking.py +39 -0
- zabob_houdini-0.1.3/tests/test_enhanced_copy.py +81 -0
- zabob_houdini-0.1.3/tests/test_houdini_bridge.py +165 -0
- zabob_houdini-0.1.3/tests/test_houdini_integration.py +102 -0
- zabob_houdini-0.1.3/tests/test_input_connections.py +61 -0
- zabob_houdini-0.1.3/tests/test_input_validation.py +87 -0
- zabob_houdini-0.1.3/tests/test_node_context.py +174 -0
- zabob_houdini-0.1.3/tests/test_node_creation.py +78 -0
- zabob_houdini-0.1.3/tests/test_node_duplication.py +64 -0
- zabob_houdini-0.1.3/tests/test_simple.py +19 -0
- zabob_houdini-0.1.3/uv.lock +657 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Houdini Python environment setup for Linux
|
|
3
|
+
# Copy this to .env and adjust paths if your Houdini installation differs
|
|
4
|
+
|
|
5
|
+
# Standard Houdini installation paths on Linux
|
|
6
|
+
HOUDINI_PATH="/opt/hfs19.5.640"
|
|
7
|
+
|
|
8
|
+
# Alternative paths for different versions or locations:
|
|
9
|
+
# HOUDINI_PATH="/opt/hfs20.0.547"
|
|
10
|
+
# HOUDINI_PATH="/usr/local/houdini/hfs19.5.640"
|
|
11
|
+
# HOUDINI_PATH="/home/user/houdini/hfs19.5.640"
|
|
12
|
+
|
|
13
|
+
# Python path setup for VS Code IntelliSense
|
|
14
|
+
PYTHONPATH="${HOUDINI_PATH}/houdini/python3.11libs:${PYTHONPATH}"
|
|
15
|
+
|
|
16
|
+
# SideFX credentials (optional) - required for Houdini installer download functionality
|
|
17
|
+
# Create an account at https://www.sidefx.com/login/ to get these credentials
|
|
18
|
+
# SIDEFX_USERNAME=""
|
|
19
|
+
# SIDEFX_PASSWORD=""
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Houdini Python environment setup for macOS
|
|
3
|
+
# Copy this to .env and adjust paths if your Houdini installation differs
|
|
4
|
+
|
|
5
|
+
# Standard Houdini installation path on macOS
|
|
6
|
+
HOUDINI_PATH="/Applications/Houdini/Current/Frameworks/Houdini.framework/Versions/Current/Resources"
|
|
7
|
+
|
|
8
|
+
# Alternative paths for different versions:
|
|
9
|
+
# HOUDINI_PATH="/Applications/Houdini/Houdini19.5.640/Frameworks/Houdini.framework/Versions/19.5.640/Resources"
|
|
10
|
+
# HOUDINI_PATH="/Applications/Houdini/Houdini20.0.547/Frameworks/Houdini.framework/Versions/20.0.547/Resources"
|
|
11
|
+
|
|
12
|
+
# Python path setup for VS Code IntelliSense
|
|
13
|
+
PYTHONPATH="${HOUDINI_PATH}/houdini/python3.11libs:${PYTHONPATH}"
|
|
14
|
+
|
|
15
|
+
# SideFX credentials (optional) - required for Houdini installer download functionality
|
|
16
|
+
# Create an account at https://www.sidefx.com/login/ to get these credentials
|
|
17
|
+
# SIDEFX_USERNAME=""
|
|
18
|
+
# SIDEFX_PASSWORD=""
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Houdini Python environment setup for Windows
|
|
3
|
+
# Copy this to .env and adjust paths if your Houdini installation differs
|
|
4
|
+
|
|
5
|
+
# Standard Houdini installation paths on Windows
|
|
6
|
+
HOUDINI_PATH="C:/Program Files/Side Effects Software/Houdini 19.5.640"
|
|
7
|
+
|
|
8
|
+
# Alternative paths for different versions or locations:
|
|
9
|
+
# HOUDINI_PATH="C:/Program Files/Side Effects Software/Houdini 20.0.547"
|
|
10
|
+
# HOUDINI_PATH="D:/Software/Houdini/19.5.640"
|
|
11
|
+
# HOUDINI_PATH="C:/Apps/Houdini/hfs19.5.640"
|
|
12
|
+
|
|
13
|
+
# Python path setup for VS Code IntelliSense
|
|
14
|
+
PYTHONPATH="${HOUDINI_PATH}/houdini/python3.11libs;${PYTHONPATH}"
|
|
15
|
+
|
|
16
|
+
# SideFX credentials (optional) - required for Houdini installer download functionality
|
|
17
|
+
# Create an account at https://www.sidefx.com/login/ to get these credentials
|
|
18
|
+
# SIDEFX_USERNAME=""
|
|
19
|
+
# SIDEFX_PASSWORD=""
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Houdini scene files
|
|
2
|
+
*.hip filter=lfs diff=lfs merge=lfs -text
|
|
3
|
+
*.hipnc filter=lfs diff=lfs merge=lfs -text
|
|
4
|
+
*.hiplc filter=lfs diff=lfs merge=lfs -text
|
|
5
|
+
*.hda filter=lfs diff=lfs merge=lfs -text
|
|
6
|
+
*.otl filter=lfs diff=lfs merge=lfs -text
|
|
7
|
+
*.hdanc filter=lfs diff=lfs merge=lfs -text
|
|
8
|
+
|
|
9
|
+
# Houdini geometry files
|
|
10
|
+
*.bgeo filter=lfs diff=lfs merge=lfs -text
|
|
11
|
+
*.bgeo.gz filter=lfs diff=lfs merge=lfs -text
|
|
12
|
+
*.bgeo.bz2 filter=lfs diff=lfs merge=lfs -text
|
|
13
|
+
*.bgeo.sc filter=lfs diff=lfs merge=lfs -text
|
|
14
|
+
*.bgeoc filter=lfs diff=lfs merge=lfs -text
|
|
15
|
+
*.geo filter=lfs diff=lfs merge=lfs -text
|
|
16
|
+
*.obj filter=lfs diff=lfs merge=lfs -text
|
|
17
|
+
*.ply filter=lfs diff=lfs merge=lfs -text
|
|
18
|
+
*.abc filter=lfs diff=lfs merge=lfs -text
|
|
19
|
+
*.fbx filter=lfs diff=lfs merge=lfs -text
|
|
20
|
+
*.dae filter=lfs diff=lfs merge=lfs -text
|
|
21
|
+
|
|
22
|
+
# Houdini image/texture files
|
|
23
|
+
*.pic filter=lfs diff=lfs merge=lfs -text
|
|
24
|
+
*.rat filter=lfs diff=lfs merge=lfs -text
|
|
25
|
+
*.exr filter=lfs diff=lfs merge=lfs -text
|
|
26
|
+
*.hdr filter=lfs diff=lfs merge=lfs -text
|
|
27
|
+
*.tif filter=lfs diff=lfs merge=lfs -text
|
|
28
|
+
*.tiff filter=lfs diff=lfs merge=lfs -text
|
|
29
|
+
*.tga filter=lfs diff=lfs merge=lfs -text
|
|
30
|
+
*.png filter=lfs diff=lfs merge=lfs -text
|
|
31
|
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
|
32
|
+
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
|
33
|
+
|
|
34
|
+
# Houdini simulation cache files
|
|
35
|
+
*.sim filter=lfs diff=lfs merge=lfs -text
|
|
36
|
+
*.simdata filter=lfs diff=lfs merge=lfs -text
|
|
37
|
+
*.sc filter=lfs diff=lfs merge=lfs -text
|
|
38
|
+
|
|
39
|
+
# Houdini rendering files
|
|
40
|
+
*.ifd filter=lfs diff=lfs merge=lfs -text
|
|
41
|
+
*.ass filter=lfs diff=lfs merge=lfs -text
|
|
42
|
+
*.rib filter=lfs diff=lfs merge=lfs -text
|
|
43
|
+
*.mi filter=lfs diff=lfs merge=lfs -text
|
|
44
|
+
|
|
45
|
+
# Houdini volume files
|
|
46
|
+
*.vdb filter=lfs diff=lfs merge=lfs -text
|
|
47
|
+
*.vol filter=lfs diff=lfs merge=lfs -text
|
|
48
|
+
|
|
49
|
+
# Houdini animation/mocap files
|
|
50
|
+
*.bclip filter=lfs diff=lfs merge=lfs -text
|
|
51
|
+
*.clip filter=lfs diff=lfs merge=lfs -text
|
|
52
|
+
*.chan filter=lfs diff=lfs merge=lfs -text
|
|
53
|
+
|
|
54
|
+
# Video files (often used in Houdini)
|
|
55
|
+
*.mov filter=lfs diff=lfs merge=lfs -text
|
|
56
|
+
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
|
57
|
+
*.avi filter=lfs diff=lfs merge=lfs -text
|
|
58
|
+
*.mkv filter=lfs diff=lfs merge=lfs -text
|
|
59
|
+
|
|
60
|
+
# Audio files
|
|
61
|
+
*.wav filter=lfs diff=lfs merge=lfs -text
|
|
62
|
+
*.aiff filter=lfs diff=lfs merge=lfs -text
|
|
63
|
+
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
|
64
|
+
|
|
65
|
+
# Archive files
|
|
66
|
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
|
67
|
+
*.tar.gz filter=lfs diff=lfs merge=lfs -text
|
|
68
|
+
*.tar.bz2 filter=lfs diff=lfs merge=lfs -text
|
|
69
|
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Copilot Instructions for Zabob-Houdini
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
Zabob-Houdini is a Python API for creating Houdini node graphs programmatically. This is an early-stage project that provides a simplified interface for building and connecting Houdini nodes.
|
|
5
|
+
|
|
6
|
+
## Core Architecture Concepts
|
|
7
|
+
|
|
8
|
+
### Node Graph API Design
|
|
9
|
+
- **`node()`** function: Core API for creating individual nodes
|
|
10
|
+
- Takes `NodeType`, optional name, and keyword attributes
|
|
11
|
+
- Returns `NodeInstance` objects
|
|
12
|
+
- Special `_input` keyword connects 0+ input nodes
|
|
13
|
+
- **`chain()`** function: Creates linear node sequences
|
|
14
|
+
- Connects nodes in sequence automatically
|
|
15
|
+
- Accepts `_input` for external connections
|
|
16
|
+
- Can be nested/spliced into other chains
|
|
17
|
+
- Returns `Chain` objects
|
|
18
|
+
- **Instantiation Pattern**: Both `NodeInstance` and `Chain` use `.create()` method for actual creation
|
|
19
|
+
|
|
20
|
+
### Project Structure
|
|
21
|
+
- `src/zabob_houdini/`: Main package directory
|
|
22
|
+
- Currently minimal implementation - most API described in README is not yet implemented
|
|
23
|
+
- Uses modern Python packaging with `pyproject.toml` and hatchling
|
|
24
|
+
|
|
25
|
+
## Development Conventions
|
|
26
|
+
|
|
27
|
+
### Response Guidelines
|
|
28
|
+
- **Be concise and focused** in all responses to prevent context overflow
|
|
29
|
+
- When performing code changes:
|
|
30
|
+
- Make minimal, targeted edits that address the specific request
|
|
31
|
+
- Avoid explaining what you're doing unless asked
|
|
32
|
+
- Don't repeat information already established in the conversation
|
|
33
|
+
- Skip verbose descriptions of obvious changes
|
|
34
|
+
- **Inline chat spatial signals**: When user starts with "here," "this line," "on this line," etc., make surgical changes at that exact location only
|
|
35
|
+
- **Context preservation**: Prioritize actionable content over explanatory text to maintain focus on technical work
|
|
36
|
+
|
|
37
|
+
### Python Standards
|
|
38
|
+
- **Compatibility**: Requires Python 3.11+ (pyproject.toml), for hython compatibility.
|
|
39
|
+
- Entry point: `zabob_houdini:main` console script
|
|
40
|
+
- **CLI framework**: Uses Click instead of argparse for command-line interface
|
|
41
|
+
- **Type hints**: Use modern built-in types (`list`, `dict`, `tuple`) instead of `typing.List`, etc.
|
|
42
|
+
- **Docstrings**: Write comprehensive docstrings for all public functions and classes, global variables.
|
|
43
|
+
- Docstrings for global variables should follow the definition of the variable and provide a clear description of its purpose and usage.
|
|
44
|
+
- **Modern constructs**: Use dataclasses, match statements, and other Python 3.13+ features
|
|
45
|
+
- **Parameter typing**: Declare all parameter types explicitly
|
|
46
|
+
|
|
47
|
+
### Key Files to Understand
|
|
48
|
+
- `README.md`: Contains the complete API specification and usage patterns
|
|
49
|
+
- `src/zabob_houdini/__init__.py`: Current minimal implementation
|
|
50
|
+
- `pyproject.toml`: Project configuration and dependencies
|
|
51
|
+
- `.gitignore`: Python and Houdini-specific ignore patterns
|
|
52
|
+
- `.gitattributes`: LFS configuration for Houdini binary files
|
|
53
|
+
- `.env.example.*`: Platform-specific environment variable templates (users copy to `.env`)
|
|
54
|
+
- `stubs/hou.pyi`: Type stubs for Houdini's `hou` module for development IntelliSense
|
|
55
|
+
- `TODO.md`: Deferred tasks to avoid branching work - add items here instead of implementing immediately
|
|
56
|
+
|
|
57
|
+
## Implementation Notes
|
|
58
|
+
|
|
59
|
+
### Current State
|
|
60
|
+
The project is in early development - the README describes the intended API, but implementation is minimal (just a hello world function). When implementing:
|
|
61
|
+
|
|
62
|
+
1. **Follow the README specification exactly** - it defines the expected behavior
|
|
63
|
+
2. **Implement the `node()` and `chain()` functions** as the core API
|
|
64
|
+
3. **Create `NodeInstance` and `Chain` classes** with `.create()` methods
|
|
65
|
+
4. **Handle the `_input` keyword parameter** for node connections
|
|
66
|
+
5. **Start with string-based NodeType** (SOP node names like "box", "merge")
|
|
67
|
+
6. **Defer `hou` module calls** - only execute during `.create()`, not during node definition
|
|
68
|
+
7. **Plan for NodeTypeInstance expansion** - namespace resolution for duplicate names across categories
|
|
69
|
+
|
|
70
|
+
### Integration Considerations
|
|
71
|
+
- **Abstraction Layer**: This is a Python wrapper that calls Houdini's `hou` module during `.create()` execution
|
|
72
|
+
- **Houdini Python compatibility**: Watch for potential issues with `hython` and other Houdini Python tools due to historical version constraints
|
|
73
|
+
- **NodeType Implementation**:
|
|
74
|
+
- Initially: strings representing SOP node type names (e.g., "box", "merge", "transform")
|
|
75
|
+
- Future: `NodeTypeInstance` objects to resolve namespace conflicts across categories
|
|
76
|
+
- Long-term: Context-aware validation (e.g., SOPs under `geo` nodes)
|
|
77
|
+
- **Creation Pattern**: Nodes are defined declaratively, then `.create()` calls `hou` module functions
|
|
78
|
+
|
|
79
|
+
## Testing & Development
|
|
80
|
+
- **Testing**: Uses pytest framework for testing
|
|
81
|
+
- **Package management**: Uses UV - always run `uv sync` after modifying dependencies in pyproject.toml
|
|
82
|
+
- **Code organization**: Consider dataclasses for structured data (e.g., node configurations)
|
|
83
|
+
- **Modern Python**: Leverage Python 3.13+ features like improved type hints and pattern matching
|
|
84
|
+
- No CI/CD setup yet - runs as console application via entry point
|
|
85
|
+
- Development should focus on implementing the API described in README.md first
|
|
86
|
+
|
|
87
|
+
### Test Architecture
|
|
88
|
+
- **Unit Tests**: Test object construction, equality, hashing, copying WITHOUT importing hou
|
|
89
|
+
- **NEVER mock modules** - restructure tests to avoid import issues instead
|
|
90
|
+
- Focus on dataclass behavior, caching via @functools.cache, immutability
|
|
91
|
+
- Test the API functions (node(), chain()) rather than classes directly if needed
|
|
92
|
+
- **Integration Tests**: Use `hython_test` fixture to run actual Houdini operations
|
|
93
|
+
- Never mock hou in integration tests - they should run in real Houdini environment
|
|
94
|
+
- Call functions in `houdini_test_functions.py` via the bridge
|
|
95
|
+
|
|
96
|
+
### Module Import Strategy
|
|
97
|
+
- core.py imports hou at module level - this is correct for Houdini environment
|
|
98
|
+
- Unit tests should avoid importing core directly if it causes hou import issues
|
|
99
|
+
- Integration tests run in Houdini via hython_test fixture
|
|
100
|
+
|
|
101
|
+
### Context Overflow Prevention
|
|
102
|
+
- **Be extremely concise** - this project has hit context limits multiple times
|
|
103
|
+
- When architectural changes are needed, focus on ONE specific issue at a time
|
|
104
|
+
- Don't explain what you're doing unless asked - just make the minimal change
|
|
105
|
+
- If you find yourself in an edit loop, stop and ask for clarification
|
|
106
|
+
- The core.py architecture is mature - be very cautious about major changes
|
|
107
|
+
|
|
108
|
+
### Immutable Architecture (ESTABLISHED - Don't Change)
|
|
109
|
+
- Frozen dataclasses with @functools.cache for automatic caching
|
|
110
|
+
- HashableMapping for dict fields to enable hashing
|
|
111
|
+
- Objects constructed without hou imports, hou only imported in .create() methods
|
|
112
|
+
- Identity-based hashing allows object-specific caching
|
|
113
|
+
- .copy() methods create deep copies, .create() returns cached hou.Node instances
|
|
114
|
+
|
|
115
|
+
## Task Management
|
|
116
|
+
- **TODO.md**: Use for deferred tasks to avoid branching current work
|
|
117
|
+
- When encountering complex tasks that would derail current focus, add to TODO.md instead of implementing
|
|
118
|
+
- Keep TODO.md organized with categories and clear descriptions
|
|
119
|
+
- Mark completed items and remove them periodically
|
|
120
|
+
|
|
121
|
+
## VS Code Configuration Management
|
|
122
|
+
- **Personal Settings**: `.vscode/settings.json` is personal (not committed) and created from `.vscode/settings.json.example`
|
|
123
|
+
- **Template Sync**: When `.vscode/settings.json` is modified with project-relevant changes, remind the user to update `.vscode/settings.json.example` for other contributors
|
|
124
|
+
- **Project Files**: `.vscode/project-dictionary.txt`, `.vscode/extensions.json`, and `.vscode/setup-vscode.sh` are committed
|
|
125
|
+
- **Setup Script**: New contributors use `./.vscode/setup-vscode.sh` for automated setup
|
|
126
|
+
- **Spell Checking**: Uses cSpell with project dictionary - add technical terms to `.vscode/project-dictionary.txt`
|
|
127
|
+
|
|
128
|
+
## Communication Guidelines
|
|
129
|
+
|
|
130
|
+
### Avoid Sycophantic Language
|
|
131
|
+
- **NEVER** use phrases like "You're absolutely right!", "You're absolutely correct!", "Excellent point!", or similar flattery
|
|
132
|
+
- **NEVER** validate statements as "right" when the user didn't make a factual claim that could be evaluated
|
|
133
|
+
- **NEVER** use general praise or validation as conversational filler
|
|
134
|
+
|
|
135
|
+
### Appropriate Acknowledgments
|
|
136
|
+
Use brief, factual acknowledgments only to confirm understanding of instructions:
|
|
137
|
+
- "Got it."
|
|
138
|
+
- "Ok, that makes sense."
|
|
139
|
+
- "I understand."
|
|
140
|
+
- "I see the issue."
|
|
141
|
+
|
|
142
|
+
These should only be used when:
|
|
143
|
+
1. You genuinely understand the instruction and its reasoning
|
|
144
|
+
2. The acknowledgment adds clarity about what you'll do next
|
|
145
|
+
3. You're confirming understanding of a technical requirement or constraint
|
|
146
|
+
|
|
147
|
+
### Examples
|
|
148
|
+
|
|
149
|
+
#### ❌ Inappropriate (Sycophantic)
|
|
150
|
+
User: "Yes please."
|
|
151
|
+
Assistant: "You're absolutely right! That's a great decision."
|
|
152
|
+
|
|
153
|
+
User: "Let's remove this unused code."
|
|
154
|
+
Assistant: "Excellent point! You're absolutely correct that we should clean this up."
|
|
155
|
+
|
|
156
|
+
#### ✅ Appropriate (Brief Acknowledgment)
|
|
157
|
+
User: "Yes please."
|
|
158
|
+
Assistant: "Got it." [proceeds with the requested action]
|
|
159
|
+
|
|
160
|
+
User: "Let's remove this unused code."
|
|
161
|
+
Assistant: "I'll remove the unused code path." [proceeds with removal]
|
|
162
|
+
|
|
163
|
+
#### ✅ Also Appropriate (No Acknowledgment)
|
|
164
|
+
User: "Yes please."
|
|
165
|
+
Assistant: [proceeds directly with the requested action]
|
|
166
|
+
|
|
167
|
+
### Rationale
|
|
168
|
+
- Maintains professional, technical communication
|
|
169
|
+
- Avoids artificial validation of non-factual statements
|
|
170
|
+
- Focuses on understanding and execution rather than praise
|
|
171
|
+
- Prevents misrepresenting user statements as claims that could be "right" or "wrong"
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
# Trigger on tags that look like version numbers
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- 'v*.*.*'
|
|
8
|
+
|
|
9
|
+
# Allow manual trigger from GitHub UI
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
inputs:
|
|
12
|
+
pypi_repository:
|
|
13
|
+
description: 'PyPI repository to publish to'
|
|
14
|
+
required: true
|
|
15
|
+
default: 'testpypi'
|
|
16
|
+
type: choice
|
|
17
|
+
options:
|
|
18
|
+
- testpypi
|
|
19
|
+
- pypi
|
|
20
|
+
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
id-token: write # Required for trusted publishing
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
build:
|
|
27
|
+
name: Build package
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
|
|
30
|
+
steps:
|
|
31
|
+
- name: Checkout repository
|
|
32
|
+
uses: actions/checkout@v4
|
|
33
|
+
|
|
34
|
+
- name: Set up Python
|
|
35
|
+
uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: '3.13'
|
|
38
|
+
|
|
39
|
+
- name: Install UV
|
|
40
|
+
uses: astral-sh/setup-uv@v3
|
|
41
|
+
with:
|
|
42
|
+
enable-cache: true
|
|
43
|
+
|
|
44
|
+
- name: Install dependencies
|
|
45
|
+
run: uv sync --all-extras --dev
|
|
46
|
+
|
|
47
|
+
- name: Run unit tests (excluding Houdini integration tests)
|
|
48
|
+
run: uv run pytest -m "unit and not integration" -v
|
|
49
|
+
|
|
50
|
+
- name: Run spell check
|
|
51
|
+
run: |
|
|
52
|
+
npm install
|
|
53
|
+
npm run spell-check
|
|
54
|
+
|
|
55
|
+
- name: Build package
|
|
56
|
+
run: uv build
|
|
57
|
+
|
|
58
|
+
- name: Verify package contents
|
|
59
|
+
run: |
|
|
60
|
+
echo "Built packages:"
|
|
61
|
+
ls -la dist/
|
|
62
|
+
echo "Package info:"
|
|
63
|
+
uv run python -m tarfile -l dist/*.tar.gz
|
|
64
|
+
|
|
65
|
+
- name: Upload build artifacts
|
|
66
|
+
uses: actions/upload-artifact@v4
|
|
67
|
+
with:
|
|
68
|
+
name: python-package-distributions
|
|
69
|
+
path: dist/
|
|
70
|
+
retention-days: 7
|
|
71
|
+
|
|
72
|
+
publish-testpypi:
|
|
73
|
+
name: Publish to TestPyPI
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
needs: build
|
|
76
|
+
if: github.event_name == 'workflow_dispatch' && github.event.inputs.pypi_repository == 'testpypi'
|
|
77
|
+
|
|
78
|
+
environment:
|
|
79
|
+
name: testpypi
|
|
80
|
+
url: https://test.pypi.org/p/zabob-houdini
|
|
81
|
+
|
|
82
|
+
steps:
|
|
83
|
+
- name: Download build artifacts
|
|
84
|
+
uses: actions/download-artifact@v4
|
|
85
|
+
with:
|
|
86
|
+
name: python-package-distributions
|
|
87
|
+
path: dist/
|
|
88
|
+
|
|
89
|
+
- name: Publish to TestPyPI
|
|
90
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
91
|
+
with:
|
|
92
|
+
repository-url: https://test.pypi.org/legacy/
|
|
93
|
+
print-hash: true
|
|
94
|
+
|
|
95
|
+
publish-pypi:
|
|
96
|
+
name: Publish to PyPI
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
needs: build
|
|
99
|
+
if: |
|
|
100
|
+
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
|
|
101
|
+
(github.event_name == 'workflow_dispatch' && github.event.inputs.pypi_repository == 'pypi')
|
|
102
|
+
|
|
103
|
+
environment:
|
|
104
|
+
name: pypi
|
|
105
|
+
url: https://pypi.org/p/zabob-houdini
|
|
106
|
+
|
|
107
|
+
steps:
|
|
108
|
+
- name: Download build artifacts
|
|
109
|
+
uses: actions/download-artifact@v4
|
|
110
|
+
with:
|
|
111
|
+
name: python-package-distributions
|
|
112
|
+
path: dist/
|
|
113
|
+
|
|
114
|
+
- name: Publish to PyPI
|
|
115
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
116
|
+
with:
|
|
117
|
+
print-hash: true
|
|
118
|
+
|
|
119
|
+
create-release:
|
|
120
|
+
name: Create GitHub Release
|
|
121
|
+
runs-on: ubuntu-latest
|
|
122
|
+
needs: publish-pypi
|
|
123
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
124
|
+
|
|
125
|
+
permissions:
|
|
126
|
+
contents: write
|
|
127
|
+
|
|
128
|
+
steps:
|
|
129
|
+
- name: Checkout repository
|
|
130
|
+
uses: actions/checkout@v4
|
|
131
|
+
|
|
132
|
+
- name: Download build artifacts
|
|
133
|
+
uses: actions/download-artifact@v4
|
|
134
|
+
with:
|
|
135
|
+
name: python-package-distributions
|
|
136
|
+
path: dist/
|
|
137
|
+
|
|
138
|
+
- name: Extract version from tag
|
|
139
|
+
id: version
|
|
140
|
+
run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
|
141
|
+
|
|
142
|
+
- name: Extract changelog for this version
|
|
143
|
+
id: changelog
|
|
144
|
+
run: |
|
|
145
|
+
if [ -f "CHANGELOG.md" ]; then
|
|
146
|
+
# Extract changelog section for this version
|
|
147
|
+
awk "/^## \[?v?${{ steps.version.outputs.version }}\]?/,/^## \[?v?[0-9]/ { if (/^## \[?v?[0-9]/ && !/^## \[?v?${{ steps.version.outputs.version }}\]?/) exit; print }" CHANGELOG.md | head -n -1 > changelog_section.md
|
|
148
|
+
if [ -s changelog_section.md ]; then
|
|
149
|
+
echo "changelog_content<<EOF" >> $GITHUB_OUTPUT
|
|
150
|
+
cat changelog_section.md >> $GITHUB_OUTPUT
|
|
151
|
+
echo "EOF" >> $GITHUB_OUTPUT
|
|
152
|
+
else
|
|
153
|
+
echo "changelog_content=" >> $GITHUB_OUTPUT
|
|
154
|
+
fi
|
|
155
|
+
else
|
|
156
|
+
echo "changelog_content=" >> $GITHUB_OUTPUT
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
- name: Generate release notes from commits
|
|
160
|
+
id: commits
|
|
161
|
+
run: |
|
|
162
|
+
# Get previous tag
|
|
163
|
+
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
|
|
164
|
+
if [ -n "$PREV_TAG" ]; then
|
|
165
|
+
echo "commits_content<<EOF" >> $GITHUB_OUTPUT
|
|
166
|
+
echo "### Changes since $PREV_TAG" >> $GITHUB_OUTPUT
|
|
167
|
+
echo "" >> $GITHUB_OUTPUT
|
|
168
|
+
git log --oneline --no-merges $PREV_TAG..HEAD | sed 's/^/- /' >> $GITHUB_OUTPUT
|
|
169
|
+
echo "EOF" >> $GITHUB_OUTPUT
|
|
170
|
+
else
|
|
171
|
+
echo "commits_content=" >> $GITHUB_OUTPUT
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
- name: Create GitHub Release
|
|
175
|
+
uses: softprops/action-gh-release@v2
|
|
176
|
+
with:
|
|
177
|
+
name: Release v${{ steps.version.outputs.version }}
|
|
178
|
+
body: |
|
|
179
|
+
## Zabob-Houdini v${{ steps.version.outputs.version }}
|
|
180
|
+
|
|
181
|
+
This release has been automatically published to PyPI.
|
|
182
|
+
|
|
183
|
+
### Installation
|
|
184
|
+
```bash
|
|
185
|
+
pip install zabob-houdini==${{ steps.version.outputs.version }}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Development Installation
|
|
189
|
+
```bash
|
|
190
|
+
uv add zabob-houdini==${{ steps.version.outputs.version }}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
${{ steps.changelog.outputs.changelog_content || steps.commits.outputs.commits_content || '### Changes\n\nSee the [CHANGELOG](CHANGELOG.md) for details about this release.' }}
|
|
194
|
+
files: dist/*
|
|
195
|
+
draft: false
|
|
196
|
+
prerelease: false
|
|
197
|
+
make_latest: true
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, develop ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main, develop ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
unit-tests:
|
|
11
|
+
name: Unit Tests (No Houdini)
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ['3.11', '3.12', '3.13']
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout repository
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install UV
|
|
27
|
+
uses: astral-sh/setup-uv@v3
|
|
28
|
+
with:
|
|
29
|
+
enable-cache: true
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: uv sync --all-extras --dev
|
|
33
|
+
|
|
34
|
+
- name: Run unit tests (excluding Houdini integration tests)
|
|
35
|
+
run: |
|
|
36
|
+
uv run pytest -m "unit and not integration" -v \
|
|
37
|
+
--tb=short \
|
|
38
|
+
--junit-xml=test-results-${{ matrix.python-version }}.xml
|
|
39
|
+
|
|
40
|
+
- name: Upload test results
|
|
41
|
+
uses: actions/upload-artifact@v4
|
|
42
|
+
if: always()
|
|
43
|
+
with:
|
|
44
|
+
name: test-results-${{ matrix.python-version }}
|
|
45
|
+
path: test-results-${{ matrix.python-version }}.xml
|
|
46
|
+
retention-days: 30
|
|
47
|
+
|
|
48
|
+
lint-and-type-check:
|
|
49
|
+
name: Linting and Type Checking
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
|
|
52
|
+
steps:
|
|
53
|
+
- name: Checkout repository
|
|
54
|
+
uses: actions/checkout@v4
|
|
55
|
+
|
|
56
|
+
- name: Set up Python
|
|
57
|
+
uses: actions/setup-python@v5
|
|
58
|
+
with:
|
|
59
|
+
python-version: '3.13'
|
|
60
|
+
|
|
61
|
+
- name: Install UV
|
|
62
|
+
uses: astral-sh/setup-uv@v3
|
|
63
|
+
with:
|
|
64
|
+
enable-cache: true
|
|
65
|
+
|
|
66
|
+
- name: Install dependencies
|
|
67
|
+
run: uv sync --all-extras --dev
|
|
68
|
+
|
|
69
|
+
- name: Run spell check
|
|
70
|
+
run: |
|
|
71
|
+
npm install
|
|
72
|
+
npm run spell-check
|
|
73
|
+
|
|
74
|
+
- name: Run type checking (if mypy is available)
|
|
75
|
+
run: |
|
|
76
|
+
# Test if mypy can run without segfaulting
|
|
77
|
+
if timeout 10s uv run mypy --version >/dev/null 2>&1; then
|
|
78
|
+
echo "Running mypy type checking..."
|
|
79
|
+
uv run mypy src/zabob_houdini --ignore-missing-imports || echo "MyPy found issues but continuing..."
|
|
80
|
+
else
|
|
81
|
+
echo "Mypy not available or incompatible with this Python version, skipping type checking"
|
|
82
|
+
fi
|
|
83
|
+
continue-on-error: true
|
|
84
|
+
|
|
85
|
+
integration-tests:
|
|
86
|
+
name: Integration Tests (Houdini Required)
|
|
87
|
+
runs-on: ubuntu-latest
|
|
88
|
+
# Only run integration tests on main branch or when explicitly requested
|
|
89
|
+
if: github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'test-integration')
|
|
90
|
+
|
|
91
|
+
steps:
|
|
92
|
+
- name: Checkout repository
|
|
93
|
+
uses: actions/checkout@v4
|
|
94
|
+
|
|
95
|
+
- name: Set up Python
|
|
96
|
+
uses: actions/setup-python@v5
|
|
97
|
+
with:
|
|
98
|
+
python-version: '3.13'
|
|
99
|
+
|
|
100
|
+
- name: Install UV
|
|
101
|
+
uses: astral-sh/setup-uv@v3
|
|
102
|
+
with:
|
|
103
|
+
enable-cache: true
|
|
104
|
+
|
|
105
|
+
- name: Install dependencies
|
|
106
|
+
run: uv sync --all-extras --dev
|
|
107
|
+
|
|
108
|
+
- name: Skip integration tests (Houdini not available in CI)
|
|
109
|
+
run: |
|
|
110
|
+
echo "Integration tests require Houdini installation."
|
|
111
|
+
echo "These tests are skipped in CI but can be run locally with:"
|
|
112
|
+
echo " uv run pytest tests/test_core_caching.py tests/test_houdini_integration.py -v"
|
|
113
|
+
echo ""
|
|
114
|
+
echo "To run with Houdini locally:"
|
|
115
|
+
echo "1. Install Houdini"
|
|
116
|
+
echo "2. Set up your .env file with HOUDINI_PATH"
|
|
117
|
+
echo "3. Run: uv run pytest tests/ -v"
|
|
118
|
+
exit 0
|