Metadata-Version: 2.4
Name: yaraast
Version: 2.0.1
Summary: A Python library for parsing and manipulating YARA rules using Abstract Syntax Trees
Author-email: Marc Rivero <mriverolopez@gmail.com>
License-Expression: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.4.2
Requires-Dist: rich>=13.0.0
Requires-Dist: attrs>=23.0.0
Requires-Dist: PyYAML>=6.0.0
Provides-Extra: lsp
Requires-Dist: pygls>=2.1.1; extra == "lsp"
Requires-Dist: lsprotocol>=2025.0.0; extra == "lsp"
Provides-Extra: dev
Requires-Dist: pytest>=9.0.3; extra == "dev"
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
Requires-Dist: pytest-xdist>=3.0.0; extra == "dev"
Requires-Dist: hypothesis>=6.0.0; extra == "dev"
Requires-Dist: black>=26.3.1; extra == "dev"
Requires-Dist: isort>=5.12.0; extra == "dev"
Requires-Dist: flake8>=7.0.0; extra == "dev"
Requires-Dist: flake8-docstrings>=1.7.0; extra == "dev"
Requires-Dist: flake8-bugbear>=23.0.0; extra == "dev"
Requires-Dist: flake8-comprehensions>=3.14.0; extra == "dev"
Requires-Dist: flake8-simplify>=0.20.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: mypy>=1.8.0; extra == "dev"
Requires-Dist: types-protobuf>=7.34.1; extra == "dev"
Requires-Dist: bandit>=1.7.0; extra == "dev"
Requires-Dist: pydocstyle>=6.3.0; extra == "dev"
Requires-Dist: pip-audit>=2.10.0; extra == "dev"
Requires-Dist: types-PyYAML>=6.0.0; extra == "dev"
Provides-Extra: libyara
Requires-Dist: yara-python==4.5.4; extra == "libyara"
Provides-Extra: conformance
Requires-Dist: yara-python==4.5.4; extra == "conformance"
Requires-Dist: yara-x==1.19.0; extra == "conformance"
Provides-Extra: fuzz
Requires-Dist: atheris==3.1.0; sys_platform == "linux" and extra == "fuzz"
Provides-Extra: mutation
Requires-Dist: mutmut==3.7.0; extra == "mutation"
Provides-Extra: performance
Requires-Dist: psutil>=5.9.0; extra == "performance"
Provides-Extra: visualization
Requires-Dist: graphviz>=0.20.0; extra == "visualization"
Requires-Dist: jinja2>=3.0.0; extra == "visualization"
Provides-Extra: serialization
Requires-Dist: protobuf>=7.34.1; extra == "serialization"
Provides-Extra: quality
Requires-Dist: qlty>=0.1.0; extra == "quality"
Provides-Extra: all
Requires-Dist: yaraast[dev,libyara,lsp,performance,quality,serialization,visualization]; extra == "all"
Dynamic: license-file

<p align="center">
  <img src="https://img.shields.io/badge/YARAAST-YARA%20Parser%20%26%20AST-blue?style=for-the-badge" alt="YARAAST">
</p>

<h1 align="center">yaraast</h1>

<p align="center">
  <strong>Parse, analyze, and transform YARA rules with a Python AST toolkit</strong>
</p>

<p align="center">
  <a href="https://github.com/seifreed/yaraast/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/seifreed/yaraast/ci.yml?branch=main&style=flat-square&logo=github&label=CI" alt="CI"></a>
  <a href="https://github.com/seifreed/yaraast/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License: MIT"></a>
  <img src="https://img.shields.io/badge/python-3.11--3.14-blue?style=flat-square&logo=python&logoColor=white" alt="Python 3.11-3.14">
</p>

<p align="center">
  <a href="https://github.com/seifreed/yaraast/stargazers"><img src="https://img.shields.io/github/stars/seifreed/yaraast?style=flat-square&logo=github" alt="GitHub Stars"></a>
  <a href="https://github.com/seifreed/yaraast/issues"><img src="https://img.shields.io/github/issues/seifreed/yaraast?style=flat-square&logo=github" alt="GitHub Issues"></a>
  <a href="https://github.com/seifreed/yaraast/tree/main/docs"><img src="https://img.shields.io/badge/docs-GitHub-blue?style=flat-square&logo=readthedocs&logoColor=white" alt="Docs"></a>
</p>

---

## Overview

**yaraast** is a Python library for parsing and manipulating YARA-family rules using Abstract Syntax Trees (AST). It supports classic YARA, YARA-L, and YARA-X workflows with automatic dialect detection and CLI tooling.

### Key Features

| Feature | Description |
|---------|-------------|
| **Multi-dialect Parsing** | Parse YARA, YARA-L, and YARA-X from files or strings |
| **Automatic Dialect Detection** | Unified parser auto-detects rule dialects |
| **AST Tooling** | Build, transform, diff, and serialize ASTs |
| **Formatting & Validation** | CLI commands for parse/format/validate workflows |
| **Streaming Support** | Parse very large files with streaming mode |
| **Ecosystem Integrations** | Optional LSP and libyara-related capabilities |

### Supported Rule Ecosystem

```text
Dialects   YARA, YARA-L, YARA-X
Parsers    Standard parser, unified parser, streaming parser
Outputs    YARA, JSON, YAML, AST tree views
Tooling    CLI, visitors, builders, serialization, semantic checks
```

Support levels differ by dialect. Classic YARA is stable, YARA-X is beta,
YARA-L is experimental, and automatic dialect detection is best effort. See
the [compatibility matrix](docs/compatibility.md) for the exact engines and
capabilities exercised by CI.

---

## Installation

### From PyPI (Recommended)

```bash
pip install yaraast
```

### From Source

```bash
git clone https://github.com/seifreed/yaraast.git
cd yaraast
python3 -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
pip install -e .
```

---

## Quick Start

```python
import yaraast

yara_code = """
rule example {
    strings:
        $a = "malware" nocase
    condition:
        $a
}
"""

ast = yaraast.parse(yara_code)
print(ast.rules[0].name)
```

---

## Usage

### Command Line Interface

```bash
# Parse and print normalized YARA
yaraast parse rules.yar

# Parse to JSON
yaraast parse rules.yar --format json

# Parse with explicit dialect
yaraast parse rules.yar --dialect yara-x

# Validate file (syntax + parse checks)
yaraast validate rules.yar

# Format file in-place (AST-based formatter)
yaraast fmt rules.yar

# Check formatting without modifying file
yaraast fmt rules.yar --check
```

### Core CLI Commands

| Command | Description |
|--------|-------------|
| `parse` | Parse a rule file and output YARA/JSON/YAML/tree |
| `validate` | Validate rules and run validation subcommands |
| `fmt` | AST-based formatter (with `--check` and `--diff`) |
| `format` | Format input into a target output file |
| `validate-syntax` | Syntax-focused validation entrypoint |
| `lsp` | Launch Language Server Protocol features |

---

## Python Library

### Unified Parsing

```python
from pathlib import Path

import yaraast

source = "rule example { condition: true }"

# Auto-detect dialect
ast = yaraast.parse(source)

# Force specific dialect
ast = yaraast.parse(source, dialect="yara")

# Parse files, generate new source, and format canonically
Path("rules.yar").write_text(source, encoding="utf-8")
file_ast = yaraast.parse_file("rules.yar")
generated = yaraast.generate(file_ast, dialect="yara")
formatted = yaraast.format_canonical(source, dialect="yara")

# Preserve every byte outside an explicit UTF-8 byte edit
offset = source.encode("utf-8").index(b"true")
rewritten = yaraast.rewrite_lossless(
    source,
    [yaraast.SourceEdit(offset, offset + 4, "false")],
)

# Public parsers apply bounded defaults. Override them per operation when needed.
limits = yaraast.ResourceLimits(max_input_bytes=1024 * 1024, parse_deadline=5.0)
ast = yaraast.parse(source, resource_limits=limits)

cancel = yaraast.CancellationToken()
cancel.cancel()
# yaraast.parse(source, cancellation_token=cancel) raises ParseCancelledError
```

`ResourceLimits()` disables all bounds explicitly. CLI parsing uses the public
defaults; LSP parsing uses tighter input, token, nesting, pattern, and deadline
limits and never caches a partial result after cancellation or a limit failure.

### Direct Parser + Visitor

```python
from pathlib import Path

from yaraast.parser import Parser
from yaraast.visitor import BaseVisitor

class RuleCollector(BaseVisitor):
    def __init__(self):
        self.rules = []

    def visit_rule(self, node):
        self.rules.append(node.name)
        super().visit_rule(node)

ast = Parser(Path("rules.yar").read_text(encoding="utf-8")).parse()
collector = RuleCollector()
collector.visit(ast)
print(collector.rules)
```

---

## Optional Dependencies

```bash
# LSP support
pip install yaraast[lsp]

# libyara integration
pip install yaraast[libyara]

# Performance tooling
pip install yaraast[performance]

# Visualization support
pip install yaraast[visualization]

# Everything
pip install yaraast[all]
```

## Runtime Docs

- Dialect compatibility: [docs/compatibility.md](docs/compatibility.md)
- LSP runtime internals: [docs/lsp-runtime.md](docs/lsp-runtime.md)
- LSP parity report: [docs/lsp-parity-report.md](docs/lsp-parity-report.md)
- Latest runtime benchmark artifact: [docs/benchmarks/lsp-runtime-latest.json](docs/benchmarks/lsp-runtime-latest.json)

---

## Requirements

- Python 3.11, 3.12, 3.13, or 3.14
- See [pyproject.toml](pyproject.toml) for full dependency and extras list

---

## Contributing

Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, quality checks, and workflow guidelines.

1. Fork the repository
2. Create a branch (`git checkout -b feature/your-change`)
3. Commit changes (`git commit -m "Add your change"`)
4. Push (`git push origin feature/your-change`)
5. Open a Pull Request

Project policy is documented in [SECURITY.md](SECURITY.md),
[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md), [CHANGELOG.md](CHANGELOG.md), and
[MIGRATING.md](MIGRATING.md).

---

## License

This project is licensed under the MIT License - see [LICENSE](LICENSE).

**Author**
- Marc Rivero ([mriverolopez@gmail.com](mailto:mriverolopez@gmail.com))
- Repository: [github.com/seifreed/yaraast](https://github.com/seifreed/yaraast)

---

<p align="center">
  <sub>Built for malware analysis and detection engineering workflows</sub>
</p>
