Thank you for your interest in contributing to the STL Parser project! This document provides guidelines and instructions for contributing.
- Code of Conduct
- Getting Started
- Development Workflow
- Coding Standards
- Testing Guidelines
- Commit Guidelines
- Pull Request Process
- Reporting Issues
This project adheres to a code of conduct. By participating, you are expected to uphold this code. Please be respectful and constructive in all interactions.
- Python 3.9 or higher
- Git
- Familiarity with STL specification (see docs)
-
Fork and Clone
git clone https://github.com/YOUR_USERNAME/semantic-tension-language.git cd semantic-tension-language/parser -
Create Virtual Environment
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install Dependencies
pip install -r requirements-dev.txt pip install -e . -
Verify Setup
pytest
git checkout -b feature/your-feature-nameBranch naming conventions:
feature/- New featuresbugfix/- Bug fixesdocs/- Documentation updatesrefactor/- Code refactoringtest/- Test improvements
- Write clean, readable code
- Follow coding standards (see below)
- Add/update tests for your changes
- Update documentation as needed
# Format code
black stl_parser/ tests/
# Lint code
ruff stl_parser/ tests/
# Type check
mypy stl_parser/
# Run tests
pytest
# Check coverage
pytest --cov=stl_parser --cov-report=htmlgit add .
git commit -m "feat: Add new feature description"git push origin feature/your-feature-nameThen create a Pull Request on GitHub.
- PEP 8 compliance (enforced by black and ruff)
- Line length: 100 characters maximum
- Type hints: All functions must have type annotations
- Docstrings: All public functions/classes must have docstrings
from typing import List, Optional
from pydantic import BaseModel
class Statement(BaseModel):
"""Represents an STL statement.
Args:
source: Source anchor
target: Target anchor
modifiers: Optional modifiers
Raises:
ValueError: If anchors are invalid
"""
source: str
target: str
modifiers: Optional[dict] = None
def validate(self) -> bool:
"""Validate the statement.
Returns:
True if valid, False otherwise
"""
return self.source and self.targetUse Google-style docstrings:
def parse(text: str, mode: str = "strict") -> ParseResult:
"""Parse STL text into structured format.
Args:
text: STL text to parse
mode: Validation mode ("strict", "lenient", or "validation")
Returns:
ParseResult containing statements and any errors
Raises:
ValueError: If mode is invalid
ParseError: If text cannot be parsed
Example:
>>> parser = STLParser()
>>> result = parser.parse("[A] → [B]")
>>> result.is_valid
True
"""
passtests/
├── conftest.py # Shared fixtures
├── test_parser.py # Parser tests
├── test_validator.py # Validator tests
├── test_serializer.py # Serializer tests
├── test_roundtrip.py # Round-trip tests
└── fixtures/
├── valid/ # Valid STL examples
├── invalid/ # Invalid STL examples
└── edge_cases/ # Edge case examples
import pytest
from stl_parser import STLParser, ParseError
class TestParser:
"""Test suite for parser functionality."""
@pytest.fixture
def parser(self):
"""Create parser instance."""
return STLParser()
def test_simple_statement(self, parser):
"""Test parsing simple statement."""
result = parser.parse("[A] → [B]")
assert result.is_valid
assert len(result.statements) == 1
def test_invalid_anchor(self, parser):
"""Test error on invalid anchor."""
result = parser.parse("[Invalid!]")
assert not result.is_valid
assert result.errors[0].code == "E001"
@pytest.mark.parametrize("input,expected", [
("[A] → [B]", True),
("[A] [B]", False),
("[A] → [B] → [C]", True),
])
def test_multiple_cases(self, parser, input, expected):
"""Test multiple input cases."""
result = parser.parse(input)
assert result.is_valid == expected- Minimum coverage: 90%
- Critical paths: 100% coverage
- Edge cases: Must be tested
- Error paths: Must be tested
# Run all tests
pytest
# Run specific test file
pytest tests/test_parser.py
# Run specific test
pytest tests/test_parser.py::TestParser::test_simple_statement
# Run with coverage
pytest --cov=stl_parser --cov-report=html
# Run only fast tests
pytest -m "not slow"
# Run in parallel
pytest -n auto<type>(<scope>): <subject>
<body>
<footer>
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, etc.)refactor: Code refactoringtest: Test additions/changeschore: Build process or tooling changes
# Feature
git commit -m "feat(parser): Add support for chained paths"
# Bug fix
git commit -m "fix(validator): Correct confidence range validation"
# Documentation
git commit -m "docs: Update README with new examples"
# Multiple paragraphs
git commit -m "feat(serializer): Add RDF/Turtle export
Implements RDF serialization according to spec Section 6.
Uses rdflib for robust RDF generation.
Closes #123"- Atomic commits: One logical change per commit
- Clear messages: Explain what and why, not how
- Reference issues: Use
Closes #123orFixes #456 - Keep it small: Prefer many small commits over large ones
- ✅ All tests pass
- ✅ Code coverage ≥ 90%
- ✅ Linters pass (black, ruff, mypy)
- ✅ Documentation updated
- ✅ CHANGELOG updated (if applicable)
- ✅ Commits follow guidelines
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing performed
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review performed
- [ ] Comments added for complex code
- [ ] Documentation updated
- [ ] Tests pass locally
- [ ] No new warnings generated
## Related Issues
Closes #(issue number)- Automated checks: CI must pass
- Code review: At least one approval required
- Discussion: Address all review comments
- Updates: Push fixes to same branch
- Merge: Squash and merge when approved
- Search existing issues: Avoid duplicates
- Check documentation: Issue might be explained
- Try latest version: Bug might be fixed
## Description
Clear description of the issue
## Steps to Reproduce
1. Step one
2. Step two
3. Step three
## Expected Behavior
What should happen
## Actual Behavior
What actually happens
## Environment
- OS: [e.g., Windows 11, Ubuntu 22.04]
- Python version: [e.g., 3.11.2]
- STL Parser version: [e.g., 1.0.0]
## Additional Context
Any other relevant information- Bug Report: Something isn't working
- Feature Request: Suggest new functionality
- Documentation: Improve or add documentation
- Question: Ask for help or clarification
# Enable verbose logging
import logging
logging.basicConfig(level=logging.DEBUG)
# Use ipdb for debugging
import ipdb; ipdb.set_trace()import time
from stl_parser import STLParser
parser = STLParser()
start = time.time()
result = parser.parse(large_stl_text)
elapsed = time.time() - start
print(f"Parsed in {elapsed:.2f}s")# Create test fixtures
mkdir -p tests/fixtures/valid
echo "[A] → [B]" > tests/fixtures/valid/simple.stl
# Run parser on fixture
stl validate tests/fixtures/valid/simple.stl- STL Specification
- Implementation Plan
- Lark Parser Documentation
- Pydantic Documentation
- pytest Documentation
- GitHub Discussions: For questions and discussions
- GitHub Issues: For bug reports and feature requests
- Email: contact@scos-lab.org
Thank you for contributing to STL Parser! 🎉