Skip to content

Coding Standards

Coding Standards

Follow these standards when contributing to pyrs-yaml.

Rust

Style

  • Use cargo fmt before 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, # Examples sections
  • 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() or py.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 (run ruff 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 pytest with 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 test and uv 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