Coding Standards
Coding Standards¶
Follow these standards when contributing to pyrs-yaml.
Rust¶
Style¶
- Use
cargo fmtbefore committing - Follow Rust API Guidelines
- Use
#[allow(unused_imports)]only when necessary (tests, feature flags)
Error Handling¶
- Never use
.unwrap()or.expect()in business logic - Convert all Rust errors to Python exceptions
- Use
PyResult<T>for functions that can fail - Map specific errors to specific Python exception types
Good vs bad error handling
// Good
let content = std::fs::read_to_string(path)
.map_err(|e| YamlParseError::new_err(format_i18n_error("file-read-error", ...)))?;
// Bad
let content = std::fs::read_to_string(path).unwrap();
Documentation¶
- All public functions must have
///doc comments - Include
# Arguments,# Returns,# Errors,# Examplessections - Write doc comments in English (Rust convention)
- Chinese doc comments are acceptable for internal functions
Doc comment template
/// Parse a YAML string into a CustomNode AST.
///
/// # Arguments
/// * `yaml` - YAML content string
///
/// # Returns
/// The parsed AST root node, or `Err(String)` on failure
///
/// # Errors
/// Returns `Err(String)` formatted as `"YAML parse error: line N, col M: <msg>"`
///
/// # Examples
/// ```
/// let ast = pyrs_yaml::parser::parse("key: value").unwrap();
/// ```
pub fn parse(yaml: &str) -> Result<CustomNode, String> {
PyO3 Signature Annotations¶
Every #[pyfunction] and #[pymethods] must use #[pyo3(signature = "...")] with quoted types:
PyO3 signature annotation
#[pyo3(signature = (yaml: "str", resolve_merges: "bool" = true, schema: "str" = "core") -> "YamlDocument")]
fn parse(...) -> YamlDocument { ... }
GIL Management¶
- Release GIL during heavy computation using
py.detach()orpy.allow_threads() - Never hold GIL during file I/O or parsing
GIL release
// Good
let ast = py.detach(|| {
parser::parse_with_options(&yaml_str, resolve_merges)
.map_err(|e| YamlParseError::new_err(...))?
})?;
// Bad — holds GIL during parsing
let ast = parser::parse_with_options(&yaml_str, resolve_merges)?;
Clippy¶
Run cargo clippy -- -D warnings — treat all warnings as errors.
Python¶
Style¶
- Follow PEP 8
- Use type hints everywhere
- Docstrings in Google style
- Linting is configured in
ruff.toml(runruff check)
Python docstring style
def parse(yaml: str, resolve_merges: bool = True, schema: str = "core") -> YamlDocument:
"""Parse a YAML string into a YamlDocument.
Args:
yaml: A string containing YAML content
resolve_merges: Whether to resolve merge keys (default: True)
schema: YAML schema profile ("core", "json", "failsafe", "yaml11")
Returns:
A YamlDocument containing the parsed YAML
Raises:
YamlParseError: If the YAML is invalid
"""
Testing¶
- Write tests before code (TDD)
- Use
uv run --frozen pytestwith fixtures where appropriate - Test edge cases: empty input, special characters, large documents
- Include round-trip assertions
- Pytest config is in
pytest.ini(asyncio_mode = auto, custom markers)
Git¶
- Commit messages in imperative mood: "Add feature X", not "Added feature X"
- One logical change per commit
- Run
cargo testanduv run --frozen pytest tests/before committing
Documentation¶
- Update docs when changing behavior
- Use code examples that can be copy-pasted and run
- Keep examples concise but complete