behave-model 1.0.0__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.
Files changed (70) hide show
  1. behave_model-1.0.0/.github/workflows/ci.yml +47 -0
  2. behave_model-1.0.0/.github/workflows/docs.yml +52 -0
  3. behave_model-1.0.0/.github/workflows/release.yml +85 -0
  4. behave_model-1.0.0/.gitignore +78 -0
  5. behave_model-1.0.0/.pre-commit-config.yaml +7 -0
  6. behave_model-1.0.0/CHANGELOG.md +54 -0
  7. behave_model-1.0.0/LICENSE +21 -0
  8. behave_model-1.0.0/Makefile +37 -0
  9. behave_model-1.0.0/PKG-INFO +273 -0
  10. behave_model-1.0.0/README.md +241 -0
  11. behave_model-1.0.0/behave_model/__init__.py +164 -0
  12. behave_model-1.0.0/behave_model/exceptions.py +28 -0
  13. behave_model-1.0.0/behave_model/model/__init__.py +34 -0
  14. behave_model-1.0.0/behave_model/model/background.py +39 -0
  15. behave_model-1.0.0/behave_model/model/comment.py +23 -0
  16. behave_model-1.0.0/behave_model/model/docstring.py +29 -0
  17. behave_model-1.0.0/behave_model/model/examples.py +44 -0
  18. behave_model-1.0.0/behave_model/model/feature.py +113 -0
  19. behave_model-1.0.0/behave_model/model/location.py +30 -0
  20. behave_model-1.0.0/behave_model/model/metadata.py +23 -0
  21. behave_model-1.0.0/behave_model/model/project.py +208 -0
  22. behave_model-1.0.0/behave_model/model/rule.py +83 -0
  23. behave_model-1.0.0/behave_model/model/scenario.py +56 -0
  24. behave_model-1.0.0/behave_model/model/scenario_outline.py +69 -0
  25. behave_model-1.0.0/behave_model/model/step.py +57 -0
  26. behave_model-1.0.0/behave_model/model/table.py +93 -0
  27. behave_model-1.0.0/behave_model/model/tag.py +31 -0
  28. behave_model-1.0.0/behave_model/parser/__init__.py +13 -0
  29. behave_model-1.0.0/behave_model/parser/adapter.py +240 -0
  30. behave_model-1.0.0/behave_model/parser/loader.py +82 -0
  31. behave_model-1.0.0/behave_model/parser/parser.py +46 -0
  32. behave_model-1.0.0/behave_model/queries/__init__.py +25 -0
  33. behave_model-1.0.0/behave_model/queries/query.py +155 -0
  34. behave_model-1.0.0/behave_model/serializers/__init__.py +11 -0
  35. behave_model-1.0.0/behave_model/serializers/dict_serializer.py +165 -0
  36. behave_model-1.0.0/behave_model/serializers/json_serializer.py +41 -0
  37. behave_model-1.0.0/behave_model/serializers/pretty_printer.py +191 -0
  38. behave_model-1.0.0/behave_model/transformations/__init__.py +23 -0
  39. behave_model-1.0.0/behave_model/transformations/transform.py +192 -0
  40. behave_model-1.0.0/behave_model/utils/__init__.py +15 -0
  41. behave_model-1.0.0/behave_model/utils/utils.py +29 -0
  42. behave_model-1.0.0/behave_model/validation/__init__.py +23 -0
  43. behave_model-1.0.0/behave_model/validation/validator.py +228 -0
  44. behave_model-1.0.0/behave_model/visitors/__init__.py +13 -0
  45. behave_model-1.0.0/behave_model/visitors/visitor.py +142 -0
  46. behave_model-1.0.0/conftest.py +12 -0
  47. behave_model-1.0.0/docs/api_reference.md +146 -0
  48. behave_model-1.0.0/docs/architecture.md +89 -0
  49. behave_model-1.0.0/docs/contributing.md +57 -0
  50. behave_model-1.0.0/docs/index.md +49 -0
  51. behave_model-1.0.0/docs/quick_start.md +100 -0
  52. behave_model-1.0.0/examples/data_tables.feature +20 -0
  53. behave_model-1.0.0/examples/login.feature +35 -0
  54. behave_model-1.0.0/examples/rules.feature +36 -0
  55. behave_model-1.0.0/examples/shopping_cart.feature +30 -0
  56. behave_model-1.0.0/mkdocs.yml +63 -0
  57. behave_model-1.0.0/pyproject.toml +70 -0
  58. behave_model-1.0.0/tests/conftest.py +135 -0
  59. behave_model-1.0.0/tests/test_exceptions.py +31 -0
  60. behave_model-1.0.0/tests/test_golden.py +120 -0
  61. behave_model-1.0.0/tests/test_model.py +321 -0
  62. behave_model-1.0.0/tests/test_parser.py +144 -0
  63. behave_model-1.0.0/tests/test_query.py +117 -0
  64. behave_model-1.0.0/tests/test_rules.py +270 -0
  65. behave_model-1.0.0/tests/test_serialization.py +157 -0
  66. behave_model-1.0.0/tests/test_statistics.py +71 -0
  67. behave_model-1.0.0/tests/test_transformation.py +133 -0
  68. behave_model-1.0.0/tests/test_validation.py +183 -0
  69. behave_model-1.0.0/tests/test_visitor.py +104 -0
  70. behave_model-1.0.0/tox.ini +22 -0
@@ -0,0 +1,47 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+ branches: [main, master]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.11"
17
+ - run: pip install ruff
18
+ - run: ruff check behave_model/ tests/
19
+ - run: ruff format --check behave_model/ tests/
20
+
21
+ test:
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ matrix:
25
+ python-version: ["3.11", "3.12", "3.13"]
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: ${{ matrix.python-version }}
31
+ - run: pip install -e ".[dev]"
32
+ - run: python -m pytest tests/ --cov=behave_model --cov-report=xml --cov-report=term
33
+ - uses: codecov/codecov-action@v4
34
+ with:
35
+ file: ./coverage.xml
36
+ fail_ci_if_error: false
37
+
38
+ packaging:
39
+ runs-on: ubuntu-latest
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+ - uses: actions/setup-python@v5
43
+ with:
44
+ python-version: "3.11"
45
+ - run: pip install build twine
46
+ - run: python -m build
47
+ - run: python -m twine check dist/*
@@ -0,0 +1,52 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths:
8
+ - "docs/**"
9
+ - "mkdocs.yml"
10
+ - "README.md"
11
+ workflow_dispatch:
12
+
13
+ permissions:
14
+ contents: read
15
+ pages: write
16
+ id-token: write
17
+
18
+ concurrency:
19
+ group: "pages"
20
+ cancel-in-progress: false
21
+
22
+ jobs:
23
+ build:
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: "3.12"
31
+
32
+ - name: Install MkDocs
33
+ run: pip install mkdocs mkdocs-material
34
+
35
+ - name: Build site
36
+ run: mkdocs build --strict
37
+
38
+ - name: Upload artifact
39
+ uses: actions/upload-pages-artifact@v3
40
+ with:
41
+ path: site
42
+
43
+ deploy:
44
+ needs: build
45
+ runs-on: ubuntu-latest
46
+ environment:
47
+ name: github-pages
48
+ url: ${{ steps.deployment.outputs.page_url }}
49
+ steps:
50
+ - name: Deploy to GitHub Pages
51
+ id: deployment
52
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,85 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: write
10
+ id-token: write
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ matrix:
17
+ python-version: ["3.11", "3.12", "3.13"]
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+ - run: pip install -e ".[dev]"
24
+ - run: python -m pytest tests/ --cov=behave_model --cov-report=term
25
+
26
+ build:
27
+ needs: test
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+
32
+ - uses: actions/setup-python@v5
33
+ with:
34
+ python-version: "3.12"
35
+
36
+ - name: Install build dependencies
37
+ run: pip install build twine
38
+
39
+ - name: Build distributions
40
+ run: python -m build
41
+
42
+ - name: Check distributions
43
+ run: python -m twine check dist/*
44
+
45
+ - name: Upload distributions
46
+ uses: actions/upload-artifact@v4
47
+ with:
48
+ name: dist
49
+ path: dist/
50
+
51
+ publish-pypi:
52
+ needs: build
53
+ runs-on: ubuntu-latest
54
+ environment: pypi
55
+ permissions:
56
+ id-token: write
57
+ steps:
58
+ - name: Download distributions
59
+ uses: actions/download-artifact@v4
60
+ with:
61
+ name: dist
62
+ path: dist/
63
+
64
+ - name: Publish to PyPI
65
+ uses: pypa/gh-action-pypi-publish@release/v1
66
+
67
+ github-release:
68
+ needs: build
69
+ runs-on: ubuntu-latest
70
+ permissions:
71
+ contents: write
72
+ steps:
73
+ - uses: actions/checkout@v4
74
+
75
+ - name: Download distributions
76
+ uses: actions/download-artifact@v4
77
+ with:
78
+ name: dist
79
+ path: dist/
80
+
81
+ - name: Create GitHub Release
82
+ uses: softprops/action-gh-release@v2
83
+ with:
84
+ generate_release_notes: true
85
+ files: dist/*
@@ -0,0 +1,78 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Installer logs
34
+ pip-log.txt
35
+ pip-delete-this-directory.txt
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ .pytest_cache/
45
+ nosetests.xml
46
+ coverage.xml
47
+ *.cover
48
+ *.py,cover
49
+ .hypothesis/
50
+ *.lcov
51
+
52
+ # Environments
53
+ .env
54
+ .venv
55
+ env/
56
+ venv/
57
+ ENV/
58
+ env.bak/
59
+ venv.bak/
60
+
61
+ # IDEs
62
+ .idea/
63
+ .vscode/
64
+ *.swp
65
+ *.swo
66
+ *~
67
+ .DS_Store
68
+
69
+ # Type checkers
70
+ .mypy_cache/
71
+ .pyre/
72
+ .pytype/
73
+
74
+ # Ruff
75
+ .ruff_cache/
76
+
77
+ # MkDocs
78
+ site/
@@ -0,0 +1,7 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.5.0
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
@@ -0,0 +1,54 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2026-07-02
9
+
10
+ ### Added
11
+ - `Rule` model class for Gherkin v6 `Rule` keyword support.
12
+ - `Feature.rules` list and `Feature.all_scenarios()` now includes rule scenarios.
13
+ - `BehaveParserAdapter._adapt_rule()` to parse Behave Rule objects.
14
+ - `Visitor.visit_rule()` in base visitor, `CountingVisitor`, and `CollectingVisitor`.
15
+ - `Project` DFS/BFS traversal now includes Rule nodes.
16
+ - `DictSerializer.serialize_rule()` and rules in `serialize_feature()`.
17
+ - `PrettyPrinter._print_rule()` with proper indentation for rule scenarios.
18
+ - `Rule` exported in public API (`behave_model.Rule`).
19
+ - Example feature file `examples/rules.feature` demonstrating Gherkin v6 Rules.
20
+ - 31 new tests for Rule support in `tests/test_rules.py`.
21
+ - MkDocs Material documentation site with GitHub Pages deployment.
22
+ - CI/CD workflows: `ci.yml`, `release.yml`, `docs.yml`.
23
+ - `.gitignore`, `.pre-commit-config.yaml`, `tox.ini`, `Makefile`, `conftest.py`.
24
+
25
+ ### Changed
26
+ - Tests moved from `behave_model/tests/` to `tests/` at project root.
27
+ - `pyproject.toml` `testpaths` updated to `["tests"]`.
28
+ - `PrettyPrinter` scenario/outline/examples methods now accept `indent` parameter.
29
+ - `Project.all_scenarios()` delegates to `Feature.all_scenarios()` for rule inclusion.
30
+ - README rewritten with badges, compatibility table, and architecture overview.
31
+
32
+ ### Compatibility
33
+ - Verified full compatibility with Behave 1.3.3.
34
+ - Verified Tag Expression v2 support (both v1 and v2 parsers present in Behave).
35
+ - Verified Gherkin v6 `Rule` keyword parsing and roundtrip.
36
+
37
+ ## [0.1.0] - 2026-07-01
38
+
39
+ ### Added
40
+ - Initial release of `behave-model`.
41
+ - Domain model: `Project`, `Feature`, `Background`, `Scenario`, `ScenarioOutline`,
42
+ `Examples`, `Step`, `Table`, `Tag`, `DocString`, `Comment`, `Location`, `Metadata`.
43
+ - Parser adapter over Behave's built-in parser with `load_project` and `load_feature`.
44
+ - Visitor pattern with depth-first and breadth-first traversal.
45
+ - Query API: `find_feature`, `find_tag`, `find_steps`, `find_scenarios`.
46
+ - Serializers: dictionary and JSON.
47
+ - Transformations: rename tag, rename scenario, sort tags, sort features,
48
+ normalize whitespace.
49
+ - Validation framework with pluggable rules.
50
+ - Statistics: feature count, scenario count, step count, average steps per
51
+ scenario, tag count.
52
+ - Pretty printer that generates valid `.feature` files.
53
+ - Exception hierarchy: `BehaveModelError`, `ParseError`, `ValidationError`,
54
+ `TransformationError`, `SerializationError`.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mathias Paulenko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,37 @@
1
+ .PHONY: install dev test test-verbose lint format coverage build clean docs docs-serve
2
+
3
+ install:
4
+ pip install -e .
5
+
6
+ dev:
7
+ pip install -e ".[dev]"
8
+
9
+ test:
10
+ pytest tests/ -q
11
+
12
+ test-verbose:
13
+ pytest tests/ -v --tb=short
14
+
15
+ lint:
16
+ ruff check behave_model/ tests/
17
+ ruff format --check behave_model/ tests/
18
+
19
+ format:
20
+ ruff format behave_model/ tests/
21
+ ruff check --fix behave_model/ tests/
22
+
23
+ coverage:
24
+ pytest tests/ --cov=behave_model --cov-report=term-missing --cov-report=html
25
+
26
+ build:
27
+ python -m build
28
+
29
+ docs:
30
+ mkdocs build --strict
31
+
32
+ docs-serve:
33
+ mkdocs serve
34
+
35
+ clean:
36
+ rm -rf build/ dist/ *.egg-info/ .coverage .pytest_cache/ htmlcov/ .tox/ .ruff_cache/
37
+ find . -type d -name __pycache__ -exec rm -rf {} +
@@ -0,0 +1,273 @@
1
+ Metadata-Version: 2.4
2
+ Name: behave-model
3
+ Version: 1.0.0
4
+ Summary: Canonical object model for Behave projects
5
+ Project-URL: Homepage, https://github.com/MathiasPaulenko/behave-model
6
+ Project-URL: Repository, https://github.com/MathiasPaulenko/behave-model
7
+ Project-URL: Issues, https://github.com/MathiasPaulenko/behave-model/issues
8
+ Project-URL: Documentation, https://mathiaspaulenko.github.io/behave-model/
9
+ Project-URL: Changelog, https://github.com/MathiasPaulenko/behave-model/blob/main/CHANGELOG.md
10
+ Author: Mathias Paulenko
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: bdd,behave,cucumber,domain,gherkin,model,testing
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Topic :: Software Development :: Testing
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: behave>=1.2.6
25
+ Provides-Extra: dev
26
+ Requires-Dist: mkdocs-material>=9.5; extra == 'dev'
27
+ Requires-Dist: mkdocs>=1.6; extra == 'dev'
28
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
29
+ Requires-Dist: pytest>=8.0; extra == 'dev'
30
+ Requires-Dist: ruff>=0.5; extra == 'dev'
31
+ Description-Content-Type: text/markdown
32
+
33
+ <div align="center">
34
+
35
+ # behave-model
36
+
37
+ **The canonical object model for [Behave](https://github.com/behave/behave) projects.**
38
+
39
+ [![CI](https://github.com/MathiasPaulenko/behave-model/actions/workflows/ci.yml/badge.svg)](https://github.com/MathiasPaulenko/behave-model/actions/workflows/ci.yml)
40
+ [![PyPI](https://img.shields.io/pypi/v/behave-model.svg)](https://pypi.org/project/behave-model/)
41
+ [![Python](https://img.shields.io/pypi/pyversions/behave-model.svg)](https://pypi.org/project/behave-model/)
42
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
43
+ [![Coverage](https://img.shields.io/badge/coverage-95%25-brightgreen)](https://github.com/MathiasPaulenko/behave-model)
44
+
45
+ [Documentation](https://mathiaspaulenko.github.io/behave-model/) · [Quick Start](https://mathiaspaulenko.github.io/behave-model/quick_start/) · [API Reference](https://mathiaspaulenko.github.io/behave-model/api_reference/)
46
+
47
+ </div>
48
+
49
+ ---
50
+
51
+ `behave-model` provides a clean, stable, and extensible Python API that represents every element of a Behave project — features, rules, scenarios, steps, tags, tables, docstrings, and more. It is the foundation for an entire ecosystem of tools: formatters, linters, analyzers, report generators, and anything else that needs to understand `.feature` files.
52
+
53
+ ## Why?
54
+
55
+ Every Behave tooling project currently parses `.feature` files independently. `behave-model` provides a single, well-tested domain model so that future tools can depend on it instead of reinventing the parser.
56
+
57
+ - **Compatible with Behave 1.3.x** — Tag Expression v2 and Gherkin v6 (including `Rule` blocks)
58
+ - **Clean domain model** — Pure dataclasses, no external runtime dependencies beyond Behave
59
+ - **Visitor pattern** — Traverse the entire tree with custom visitors
60
+ - **Query API** — Find features, scenarios, steps, and tags by name, tag, or keyword
61
+ - **Serializers** — Dict, JSON, and pretty-printed Gherkin output
62
+ - **Transformations** — Safe in-place modifications (rename tags, sort, normalize)
63
+ - **Validation framework** — Pluggable rules with built-in checks
64
+ - **95% test coverage** — Comprehensive unit, integration, and golden file tests
65
+
66
+ ## Installation
67
+
68
+ ```bash
69
+ pip install behave-model
70
+ ```
71
+
72
+ For development:
73
+
74
+ ```bash
75
+ pip install -e ".[dev]"
76
+ ```
77
+
78
+ ## Quick Start
79
+
80
+ ```python
81
+ from behave_model import load_project
82
+
83
+ # Load all .feature files from a directory
84
+ project = load_project("features/")
85
+
86
+ # Access features, rules, and scenarios
87
+ print(len(project.features)) # number of features
88
+ print(project.features[0].name) # first feature name
89
+ print(len(project.features[0].rules)) # rules (Gherkin v6)
90
+
91
+ # Query the model
92
+ for scenario in project.find_scenarios(tag="@smoke"):
93
+ print(scenario.name)
94
+
95
+ # Statistics
96
+ stats = project.statistics()
97
+ print(f"{stats['features']} features, {stats['scenarios']} scenarios, {stats['steps']} steps")
98
+
99
+ # Traverse the tree
100
+ for node in project.walk():
101
+ print(type(node).__name__)
102
+ ```
103
+
104
+ ## Domain Model
105
+
106
+ ```text
107
+ Project
108
+ ├── Metadata
109
+ ├── Feature
110
+ │ ├── Tag
111
+ │ ├── Background
112
+ │ │ └── Step
113
+ │ ├── Scenario
114
+ │ │ ├── Tag
115
+ │ │ └── Step
116
+ │ ├── ScenarioOutline
117
+ │ │ ├── Tag
118
+ │ │ ├── Step
119
+ │ │ └── Examples
120
+ │ │ └── Table
121
+ │ └── Rule (Gherkin v6)
122
+ │ ├── Tag
123
+ │ ├── Background
124
+ │ │ └── Step
125
+ │ ├── Scenario
126
+ │ └── ScenarioOutline
127
+ └── ...
128
+ ```
129
+
130
+ Every node has a `Location` (filename, line, column) for precise source mapping.
131
+
132
+ ## Features at a Glance
133
+
134
+ ### Loading
135
+
136
+ ```python
137
+ from behave_model import load_project, load_feature
138
+
139
+ project = load_project("features/") # all .feature files
140
+ feature = load_feature("features/login.feature") # single file
141
+ ```
142
+
143
+ ### Visitor Pattern
144
+
145
+ ```python
146
+ from behave_model import Visitor
147
+
148
+ class StepCounter(Visitor):
149
+ def __init__(self):
150
+ self.count = 0
151
+
152
+ def visit_step(self, step):
153
+ self.count += 1
154
+
155
+ visitor = StepCounter()
156
+ project.accept(visitor)
157
+ print(f"Total steps: {visitor.count}")
158
+ ```
159
+
160
+ ### Query API
161
+
162
+ ```python
163
+ project.find_feature("Login")
164
+ project.find_tag("@smoke")
165
+ project.find_scenarios(tag="@api")
166
+ project.find_scenarios(name_contains="login")
167
+ project.find_steps(keyword="Given")
168
+ project.find_steps(text_contains="user")
169
+ ```
170
+
171
+ ### Serialization
172
+
173
+ ```python
174
+ from behave_model import JsonSerializer, DictSerializer, PrettyPrinter
175
+
176
+ # JSON
177
+ json_str = JsonSerializer().serialize_project(project)
178
+
179
+ # Dictionary
180
+ data = DictSerializer().serialize_project(project)
181
+
182
+ # Pretty-printed Gherkin
183
+ text = PrettyPrinter().print_feature(feature)
184
+ ```
185
+
186
+ ### Transformations
187
+
188
+ ```python
189
+ from behave_model import rename_tag, sort_tags, normalize_whitespace
190
+
191
+ rename_tag(project, "@smoke", "@critical")
192
+ sort_tags(project)
193
+ normalize_whitespace(project)
194
+ ```
195
+
196
+ ### Validation
197
+
198
+ ```python
199
+ from behave_model import Validator
200
+
201
+ validator = Validator()
202
+ issues = validator.validate(project)
203
+ for issue in issues:
204
+ print(f"[{issue.severity}] {issue.rule_name}: {issue.message}")
205
+ ```
206
+
207
+ ## Architecture
208
+
209
+ ```text
210
+ Feature File → Parser Adapter → Domain Model → Visitors → Queries → Transformations → Serializers
211
+ ```
212
+
213
+ The Domain Model never depends on report generation or formatting. Each layer has a single responsibility and can be used independently.
214
+
215
+ | Layer | Package | Responsibility |
216
+ |-------|---------|----------------|
217
+ | Parser Adapter | `behave_model.parser` | Wraps Behave's parser, adapts to domain model |
218
+ | Domain Model | `behave_model.model` | Pure dataclasses for every Gherkin element |
219
+ | Visitors | `behave_model.visitors` | Generic traversal pattern |
220
+ | Queries | `behave_model.queries` | High-level filtering API |
221
+ | Transformations | `behave_model.transformations` | Safe in-place modifications |
222
+ | Serializers | `behave_model.serializers` | Dict, JSON, Gherkin output |
223
+ | Validation | `behave_model.validation` | Pluggable rule framework |
224
+
225
+ ## Compatibility
226
+
227
+ | Feature | Supported |
228
+ |---------|-----------|
229
+ | Behave 1.3.x | ✅ |
230
+ | Tag Expression v1 | ✅ |
231
+ | Tag Expression v2 | ✅ |
232
+ | Gherkin v6 (Rules) | ✅ |
233
+ | Scenario Outlines | ✅ |
234
+ | Data Tables | ✅ |
235
+ | DocStrings | ✅ |
236
+ | Background | ✅ |
237
+ | Multi-language features | ✅ |
238
+
239
+ ## Development
240
+
241
+ ```bash
242
+ # Clone and install
243
+ git clone https://github.com/MathiasPaulenko/behave-model.git
244
+ cd behave-model
245
+ pip install -e ".[dev]"
246
+
247
+ # Run tests
248
+ make test
249
+
250
+ # Run tests with coverage
251
+ make coverage
252
+
253
+ # Lint
254
+ make lint
255
+
256
+ # Format
257
+ make format
258
+
259
+ # Build
260
+ make build
261
+ ```
262
+
263
+ ## Documentation
264
+
265
+ Full documentation is available at [mathiaspaulenko.github.io/behave-model](https://mathiaspaulenko.github.io/behave-model/).
266
+
267
+ ## Contributing
268
+
269
+ Contributions are welcome! See [CONTRIBUTING.md](docs/contributing.md) for guidelines.
270
+
271
+ ## License
272
+
273
+ MIT