gd-tools-cli 0.1.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 (36) hide show
  1. gd_tools_cli-0.1.0/PKG-INFO +191 -0
  2. gd_tools_cli-0.1.0/README.md +152 -0
  3. gd_tools_cli-0.1.0/pyproject.toml +96 -0
  4. gd_tools_cli-0.1.0/setup.cfg +4 -0
  5. gd_tools_cli-0.1.0/src/gd_tools/__init__.py +3 -0
  6. gd_tools_cli-0.1.0/src/gd_tools/__main__.py +31 -0
  7. gd_tools_cli-0.1.0/src/gd_tools/addons/__init__.py +0 -0
  8. gd_tools_cli-0.1.0/src/gd_tools/addons/gd-tools-coverage/coverage.gd +43 -0
  9. gd_tools_cli-0.1.0/src/gd_tools/addons/gd-tools-coverage/post_run_hook.gd +113 -0
  10. gd_tools_cli-0.1.0/src/gd_tools/addons/gd-tools-coverage/pre_run_hook.gd +229 -0
  11. gd_tools_cli-0.1.0/src/gd_tools/cli.py +329 -0
  12. gd_tools_cli-0.1.0/src/gd_tools/config.py +289 -0
  13. gd_tools_cli-0.1.0/src/gd_tools/coverage/__init__.py +23 -0
  14. gd_tools_cli-0.1.0/src/gd_tools/coverage/cobertura_reporter.py +136 -0
  15. gd_tools_cli-0.1.0/src/gd_tools/coverage/html_reporter.py +95 -0
  16. gd_tools_cli-0.1.0/src/gd_tools/coverage/lcov_reporter.py +90 -0
  17. gd_tools_cli-0.1.0/src/gd_tools/coverage/orchestrator.py +282 -0
  18. gd_tools_cli-0.1.0/src/gd_tools/coverage/plan_generator.py +377 -0
  19. gd_tools_cli-0.1.0/src/gd_tools/coverage/reporter.py +518 -0
  20. gd_tools_cli-0.1.0/src/gd_tools/coverage/templates/file.html +72 -0
  21. gd_tools_cli-0.1.0/src/gd_tools/coverage/templates/index.html +90 -0
  22. gd_tools_cli-0.1.0/src/gd_tools/coverage/terminal_reporter.py +107 -0
  23. gd_tools_cli-0.1.0/src/gd_tools/doctor.py +495 -0
  24. gd_tools_cli-0.1.0/src/gd_tools/errors.py +79 -0
  25. gd_tools_cli-0.1.0/src/gd_tools/file_discovery.py +41 -0
  26. gd_tools_cli-0.1.0/src/gd_tools/format_runner.py +118 -0
  27. gd_tools_cli-0.1.0/src/gd_tools/godot.py +346 -0
  28. gd_tools_cli-0.1.0/src/gd_tools/init.py +619 -0
  29. gd_tools_cli-0.1.0/src/gd_tools/lint_runner.py +223 -0
  30. gd_tools_cli-0.1.0/src/gd_tools/test_runner.py +474 -0
  31. gd_tools_cli-0.1.0/src/gd_tools_cli.egg-info/PKG-INFO +191 -0
  32. gd_tools_cli-0.1.0/src/gd_tools_cli.egg-info/SOURCES.txt +34 -0
  33. gd_tools_cli-0.1.0/src/gd_tools_cli.egg-info/dependency_links.txt +1 -0
  34. gd_tools_cli-0.1.0/src/gd_tools_cli.egg-info/entry_points.txt +2 -0
  35. gd_tools_cli-0.1.0/src/gd_tools_cli.egg-info/requires.txt +18 -0
  36. gd_tools_cli-0.1.0/src/gd_tools_cli.egg-info/top_level.txt +1 -0
@@ -0,0 +1,191 @@
1
+ Metadata-Version: 2.4
2
+ Name: gd-tools-cli
3
+ Version: 0.1.0
4
+ Summary: A modern development workflow CLI for GDScript projects in Godot 4.5+
5
+ Author-email: mansyar <m.ansyarafi@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/mansyar/gd-tools
8
+ Project-URL: Repository, https://github.com/mansyar/gd-tools
9
+ Project-URL: Documentation, https://github.com/mansyar/gd-tools#readme
10
+ Project-URL: Bug Tracker, https://github.com/mansyar/gd-tools/issues
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Testing
21
+ Classifier: Topic :: Software Development :: Quality Assurance
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: gdtoolkit
25
+ Requires-Dist: click
26
+ Requires-Dist: junitparser
27
+ Requires-Dist: jinja2
28
+ Requires-Dist: rich
29
+ Requires-Dist: pyyaml
30
+ Requires-Dist: tomli; python_version < "3.11"
31
+ Requires-Dist: tomli_w
32
+ Requires-Dist: pydantic>=2.0
33
+ Requires-Dist: requests
34
+ Provides-Extra: dev
35
+ Requires-Dist: pytest; extra == "dev"
36
+ Requires-Dist: pytest-cov; extra == "dev"
37
+ Requires-Dist: ruff; extra == "dev"
38
+ Requires-Dist: black; extra == "dev"
39
+
40
+ # gd-tools
41
+
42
+ A modern development workflow CLI for GDScript projects in Godot 4.5+.
43
+
44
+ [![CI](https://github.com/mansyar/gd-tools/actions/workflows/ci.yml/badge.svg)](https://github.com/mansyar/gd-tools/actions/workflows/ci.yml)
45
+ [![Coverage](https://codecov.io/gh/mansyar/gd-tools/branch/main/graph/badge.svg)](https://codecov.io/gh/mansyar/gd-tools)
46
+ [![PyPI version](https://img.shields.io/pypi/v/gd-tools.svg)](https://pypi.org/project/gd-tools/)
47
+ [![Python versions](https://img.shields.io/pypi/pyversions/gd-tools.svg)](https://pypi.org/project/gd-tools/)
48
+ [![Godot version](https://img.shields.io/badge/Godot-4.5%2B-blue.svg)](https://godotengine.org)
49
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
50
+
51
+ ---
52
+
53
+ ## 1. Overview
54
+
55
+ `gd-tools` brings professional development tooling to GDScript -- test, lint,
56
+ format, and code coverage in a single CLI. It wraps mature, community-trusted
57
+ tools (GUT for testing, gdtoolkit for linting and formatting) and fills the
58
+ remaining gap with a custom hybrid coverage system -- production-quality line
59
+ and branch coverage for GDScript that no existing tool provides.
60
+
61
+ One install, one config, one mental model.
62
+
63
+ ## 2. Features
64
+
65
+ | Feature | Description |
66
+ |---------|-------------|
67
+ | **Unified workflow** | One install, one config (`gd-tools.toml`), one mental model for test, lint, format, and coverage. |
68
+ | **Zero-friction bootstrap** | `gd-tools init` gets a project fully set up in under a minute -- GUT installed, coverage addon deployed, configs generated. |
69
+ | **Coverage gap-filling** | Production-quality line and branch coverage for GDScript -- HTML, LCOV, and Cobertura reports that integrate with CI and code review tools. |
70
+ | **CI/CD friendly** | Exit codes, `--check` flags, machine-readable output (JSON, JUnit XML, LCOV, Cobertura), no interactive prompts in CI mode. |
71
+ | **Standalone compatibility** | gdlint, gdformat, and GUT continue to work if invoked directly. `gd-tools` is a layer on top, not a lock-in. |
72
+
73
+ ## 3. Installation
74
+
75
+ ```bash
76
+ pip install gd-tools-cli
77
+ ```
78
+
79
+ `gd-tools` requires Python 3.10+ and a Godot 4.5+ binary on your system.
80
+ The Godot binary is auto-detected from configuration, environment variables
81
+ (`GODOT_BIN`, `GODOT4_BIN`, `GODOT_PATH`), `PATH`, or common install locations.
82
+
83
+ ## 4. Quick Start
84
+
85
+ ```bash
86
+ # 1. Install
87
+ pip install gd-tools-cli
88
+
89
+ # 2. Bootstrap your Godot project
90
+ cd your-godot-project
91
+ gd-tools init
92
+
93
+ # 3. Run your tests
94
+ gd-tools test
95
+
96
+ # 4. Run tests with coverage
97
+ gd-tools test --coverage --min 80
98
+ ```
99
+
100
+ `gd-tools init` installs GUT, deploys the coverage addon, generates
101
+ `gd-tools.toml`, and creates per-tool config files (`.gutconfig.json`,
102
+ `gdlintrc`, `gdformatrc`). The command is idempotent -- safe to re-run.
103
+
104
+ ## 5. CLI Command Summary
105
+
106
+ | Command | Description |
107
+ |---------|-------------|
108
+ | `gd-tools init` | Bootstrap a Godot project -- install GUT, deploy coverage addon, generate configs. |
109
+ | `gd-tools doctor` | Diagnose the development environment -- Godot, GUT, coverage addon, tooling. |
110
+ | `gd-tools test` | Run GUT tests with optional coverage, thresholds, JUnit XML output. |
111
+ | `gd-tools lint` | Lint GDScript files using gdlint with text or JSON output. |
112
+ | `gd-tools format` | Format GDScript files using gdformat with check and diff modes. |
113
+ | `gd-tools coverage` | Coverage subcommands -- `report`, `merge`, `show`. |
114
+
115
+ See the [User Guide](./docs/USER_GUIDE.md) for full command reference,
116
+ flags, examples, and exit codes.
117
+
118
+ ## 6. Configuration
119
+
120
+ `gd-tools` uses a single `gd-tools.toml` file as the source of truth for
121
+ all tool configuration. `gd-tools init` generates this file with sensible
122
+ defaults.
123
+
124
+ ```toml
125
+ [godot]
126
+ binary = "" # Optional -- auto-detected if unset
127
+
128
+ [test]
129
+ test_dirs = ["test", "tests"]
130
+ prefix = "test_"
131
+ suffix = ".gd"
132
+ gutconfig = ".gutconfig.json"
133
+
134
+ [lint]
135
+ exclude = ["addons", ".godot", ".gd-tools", ".git"]
136
+
137
+ [format]
138
+ exclude = ["addons", ".godot", ".gd-tools", ".git"]
139
+
140
+ [coverage]
141
+ enabled = false
142
+ min_percent = 0
143
+ format = "html" # html, lcov, cobertura, text
144
+ output_dir = ".gd-tools/coverage"
145
+ exclude = ["addons", ".godot", ".gd-tools", ".git"]
146
+ test_dirs = ["test", "tests"]
147
+ ```
148
+
149
+ See the [User Guide](./docs/USER_GUIDE.md) for a full configuration reference
150
+ with all keys, defaults, and examples.
151
+
152
+ ## 7. Documentation
153
+
154
+ | Document | Description |
155
+ |----------|-------------|
156
+ | [User Guide](./docs/USER_GUIDE.md) | Complete CLI reference -- all commands, flags, examples, and troubleshooting. |
157
+ | [Contributing Guide](./docs/CONTRIBUTING.md) | Development setup, code style, testing requirements, and PR process. |
158
+ | [Architecture](./docs/ARCHITECTURE.md) | Coverage system architecture -- hybrid instrumentation design and data flows. |
159
+ | [Product Requirements](./docs/PRD.md) | Full product specification -- features, design decisions, technical detail. |
160
+ | [Roadmap](./docs/ROADMAP.md) | Release phases and milestones. |
161
+ | [Testing Strategy](./docs/TESTING_STRATEGY.md) | Test pyramid, coverage targets, and CI integration. |
162
+
163
+ ## 8. Development
164
+
165
+ ```bash
166
+ # Clone and install in editable mode with dev dependencies
167
+ git clone https://github.com/mansyar/gd-tools.git
168
+ cd gd-tools
169
+ pip install -e ".[dev]"
170
+ ```
171
+
172
+ ### Running Tests
173
+
174
+ Unit tests run without Godot. Integration tests require a Godot 4.5+
175
+ binary -- configure via `.env` (see `.env.example`):
176
+
177
+ ```bash
178
+ cp .env.example .env
179
+ # Edit .env: set GODOT_BIN to your Godot binary path
180
+
181
+ # Run all tests with coverage
182
+ pytest --cov=src/gd_tools --cov-report=term-missing
183
+ ```
184
+
185
+ See [Testing Strategy](./docs/TESTING_STRATEGY.md) for the full testing
186
+ guide and [Contributing Guide](./docs/CONTRIBUTING.md) for development
187
+ setup details.
188
+
189
+ ## 9. License
190
+
191
+ MIT
@@ -0,0 +1,152 @@
1
+ # gd-tools
2
+
3
+ A modern development workflow CLI for GDScript projects in Godot 4.5+.
4
+
5
+ [![CI](https://github.com/mansyar/gd-tools/actions/workflows/ci.yml/badge.svg)](https://github.com/mansyar/gd-tools/actions/workflows/ci.yml)
6
+ [![Coverage](https://codecov.io/gh/mansyar/gd-tools/branch/main/graph/badge.svg)](https://codecov.io/gh/mansyar/gd-tools)
7
+ [![PyPI version](https://img.shields.io/pypi/v/gd-tools.svg)](https://pypi.org/project/gd-tools/)
8
+ [![Python versions](https://img.shields.io/pypi/pyversions/gd-tools.svg)](https://pypi.org/project/gd-tools/)
9
+ [![Godot version](https://img.shields.io/badge/Godot-4.5%2B-blue.svg)](https://godotengine.org)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
11
+
12
+ ---
13
+
14
+ ## 1. Overview
15
+
16
+ `gd-tools` brings professional development tooling to GDScript -- test, lint,
17
+ format, and code coverage in a single CLI. It wraps mature, community-trusted
18
+ tools (GUT for testing, gdtoolkit for linting and formatting) and fills the
19
+ remaining gap with a custom hybrid coverage system -- production-quality line
20
+ and branch coverage for GDScript that no existing tool provides.
21
+
22
+ One install, one config, one mental model.
23
+
24
+ ## 2. Features
25
+
26
+ | Feature | Description |
27
+ |---------|-------------|
28
+ | **Unified workflow** | One install, one config (`gd-tools.toml`), one mental model for test, lint, format, and coverage. |
29
+ | **Zero-friction bootstrap** | `gd-tools init` gets a project fully set up in under a minute -- GUT installed, coverage addon deployed, configs generated. |
30
+ | **Coverage gap-filling** | Production-quality line and branch coverage for GDScript -- HTML, LCOV, and Cobertura reports that integrate with CI and code review tools. |
31
+ | **CI/CD friendly** | Exit codes, `--check` flags, machine-readable output (JSON, JUnit XML, LCOV, Cobertura), no interactive prompts in CI mode. |
32
+ | **Standalone compatibility** | gdlint, gdformat, and GUT continue to work if invoked directly. `gd-tools` is a layer on top, not a lock-in. |
33
+
34
+ ## 3. Installation
35
+
36
+ ```bash
37
+ pip install gd-tools-cli
38
+ ```
39
+
40
+ `gd-tools` requires Python 3.10+ and a Godot 4.5+ binary on your system.
41
+ The Godot binary is auto-detected from configuration, environment variables
42
+ (`GODOT_BIN`, `GODOT4_BIN`, `GODOT_PATH`), `PATH`, or common install locations.
43
+
44
+ ## 4. Quick Start
45
+
46
+ ```bash
47
+ # 1. Install
48
+ pip install gd-tools-cli
49
+
50
+ # 2. Bootstrap your Godot project
51
+ cd your-godot-project
52
+ gd-tools init
53
+
54
+ # 3. Run your tests
55
+ gd-tools test
56
+
57
+ # 4. Run tests with coverage
58
+ gd-tools test --coverage --min 80
59
+ ```
60
+
61
+ `gd-tools init` installs GUT, deploys the coverage addon, generates
62
+ `gd-tools.toml`, and creates per-tool config files (`.gutconfig.json`,
63
+ `gdlintrc`, `gdformatrc`). The command is idempotent -- safe to re-run.
64
+
65
+ ## 5. CLI Command Summary
66
+
67
+ | Command | Description |
68
+ |---------|-------------|
69
+ | `gd-tools init` | Bootstrap a Godot project -- install GUT, deploy coverage addon, generate configs. |
70
+ | `gd-tools doctor` | Diagnose the development environment -- Godot, GUT, coverage addon, tooling. |
71
+ | `gd-tools test` | Run GUT tests with optional coverage, thresholds, JUnit XML output. |
72
+ | `gd-tools lint` | Lint GDScript files using gdlint with text or JSON output. |
73
+ | `gd-tools format` | Format GDScript files using gdformat with check and diff modes. |
74
+ | `gd-tools coverage` | Coverage subcommands -- `report`, `merge`, `show`. |
75
+
76
+ See the [User Guide](./docs/USER_GUIDE.md) for full command reference,
77
+ flags, examples, and exit codes.
78
+
79
+ ## 6. Configuration
80
+
81
+ `gd-tools` uses a single `gd-tools.toml` file as the source of truth for
82
+ all tool configuration. `gd-tools init` generates this file with sensible
83
+ defaults.
84
+
85
+ ```toml
86
+ [godot]
87
+ binary = "" # Optional -- auto-detected if unset
88
+
89
+ [test]
90
+ test_dirs = ["test", "tests"]
91
+ prefix = "test_"
92
+ suffix = ".gd"
93
+ gutconfig = ".gutconfig.json"
94
+
95
+ [lint]
96
+ exclude = ["addons", ".godot", ".gd-tools", ".git"]
97
+
98
+ [format]
99
+ exclude = ["addons", ".godot", ".gd-tools", ".git"]
100
+
101
+ [coverage]
102
+ enabled = false
103
+ min_percent = 0
104
+ format = "html" # html, lcov, cobertura, text
105
+ output_dir = ".gd-tools/coverage"
106
+ exclude = ["addons", ".godot", ".gd-tools", ".git"]
107
+ test_dirs = ["test", "tests"]
108
+ ```
109
+
110
+ See the [User Guide](./docs/USER_GUIDE.md) for a full configuration reference
111
+ with all keys, defaults, and examples.
112
+
113
+ ## 7. Documentation
114
+
115
+ | Document | Description |
116
+ |----------|-------------|
117
+ | [User Guide](./docs/USER_GUIDE.md) | Complete CLI reference -- all commands, flags, examples, and troubleshooting. |
118
+ | [Contributing Guide](./docs/CONTRIBUTING.md) | Development setup, code style, testing requirements, and PR process. |
119
+ | [Architecture](./docs/ARCHITECTURE.md) | Coverage system architecture -- hybrid instrumentation design and data flows. |
120
+ | [Product Requirements](./docs/PRD.md) | Full product specification -- features, design decisions, technical detail. |
121
+ | [Roadmap](./docs/ROADMAP.md) | Release phases and milestones. |
122
+ | [Testing Strategy](./docs/TESTING_STRATEGY.md) | Test pyramid, coverage targets, and CI integration. |
123
+
124
+ ## 8. Development
125
+
126
+ ```bash
127
+ # Clone and install in editable mode with dev dependencies
128
+ git clone https://github.com/mansyar/gd-tools.git
129
+ cd gd-tools
130
+ pip install -e ".[dev]"
131
+ ```
132
+
133
+ ### Running Tests
134
+
135
+ Unit tests run without Godot. Integration tests require a Godot 4.5+
136
+ binary -- configure via `.env` (see `.env.example`):
137
+
138
+ ```bash
139
+ cp .env.example .env
140
+ # Edit .env: set GODOT_BIN to your Godot binary path
141
+
142
+ # Run all tests with coverage
143
+ pytest --cov=src/gd_tools --cov-report=term-missing
144
+ ```
145
+
146
+ See [Testing Strategy](./docs/TESTING_STRATEGY.md) for the full testing
147
+ guide and [Contributing Guide](./docs/CONTRIBUTING.md) for development
148
+ setup details.
149
+
150
+ ## 9. License
151
+
152
+ MIT
@@ -0,0 +1,96 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "gd-tools-cli"
7
+ version = "0.1.0"
8
+ description = "A modern development workflow CLI for GDScript projects in Godot 4.5+"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ {name = "mansyar", email = "m.ansyarafi@gmail.com"}
14
+ ]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Environment :: Console",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Topic :: Software Development :: Testing",
26
+ "Topic :: Software Development :: Quality Assurance",
27
+ ]
28
+ dependencies = [
29
+ "gdtoolkit",
30
+ "click",
31
+ "junitparser",
32
+ "jinja2",
33
+ "rich",
34
+ "pyyaml",
35
+ "tomli; python_version < '3.11'",
36
+ "tomli_w",
37
+ "pydantic >= 2.0",
38
+ "requests",
39
+ ]
40
+
41
+ [project.urls]
42
+ Homepage = "https://github.com/mansyar/gd-tools"
43
+ Repository = "https://github.com/mansyar/gd-tools"
44
+ Documentation = "https://github.com/mansyar/gd-tools#readme"
45
+ "Bug Tracker" = "https://github.com/mansyar/gd-tools/issues"
46
+
47
+ [project.optional-dependencies]
48
+ dev = [
49
+ "pytest",
50
+ "pytest-cov",
51
+ "ruff",
52
+ "black",
53
+ ]
54
+
55
+ [project.scripts]
56
+ gd-tools = "gd_tools.cli:cli"
57
+
58
+ [tool.setuptools.packages.find]
59
+ where = ["src"]
60
+
61
+ [tool.setuptools.package-data]
62
+ "gd_tools.addons" = ["gd-tools-coverage/*.gd"]
63
+ "gd_tools.coverage" = ["templates/*.html"]
64
+
65
+ [tool.pytest.ini_options]
66
+ testpaths = ["tests"]
67
+ markers = [
68
+ "unit: Unit tests for individual modules.",
69
+ "integration: Integration tests for command flows.",
70
+ "e2e: End-to-end tests for full workflows.",
71
+ "slow: Tests that take a long time to run.",
72
+ ]
73
+ addopts = [
74
+ "--strict-markers",
75
+ "--strict-config",
76
+ "--cov=gd_tools",
77
+ "--cov-branch",
78
+ "--cov-report=term-missing",
79
+ "--cov-report=html",
80
+ ]
81
+
82
+ [tool.coverage.run]
83
+ source = ["gd_tools"]
84
+ omit = ["*/tests/*", "*/addons/*"]
85
+
86
+ [tool.coverage.report]
87
+ fail_under = 80
88
+ show_missing = true
89
+
90
+ [tool.ruff]
91
+ line-length = 80
92
+ target-version = "py310"
93
+
94
+ [tool.black]
95
+ line-length = 80
96
+ target-version = ["py310"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """gd-tools: A modern development workflow CLI for GDScript projects."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,31 @@
1
+ """Module entry point for gd-tools.
2
+
3
+ Allows running gd-tools via ``python -m gd_tools``.
4
+ """
5
+
6
+ import sys
7
+
8
+ from .cli import cli
9
+ from .errors import GdToolsError
10
+
11
+
12
+ def main() -> None:
13
+ """Run the gd-tools CLI.
14
+
15
+ Calls the Click CLI group and catches any :class:`GdToolsError`,
16
+ printing the error message to stderr and exiting with the
17
+ exception's ``exit_code``.
18
+
19
+ Raises:
20
+ SystemExit: When the CLI exits or a :class:`GdToolsError` is
21
+ caught.
22
+ """
23
+ try:
24
+ cli()
25
+ except GdToolsError as e:
26
+ print(str(e), file=sys.stderr)
27
+ sys.exit(e.exit_code)
28
+
29
+
30
+ if __name__ == "__main__":
31
+ main()
File without changes
@@ -0,0 +1,43 @@
1
+ extends Node
2
+
3
+ # Coverage tracker autoload for gd-tools.
4
+ # Records line hit counts during GUT test execution.
5
+ # Activated via the GD_TOOLS_COVERAGE_ACTIVE environment variable.
6
+
7
+ var _hits: Dictionary = {}
8
+
9
+ var _active: bool = false
10
+
11
+
12
+ func _ready() -> void:
13
+ # Active only when GD_TOOLS_COVERAGE_ACTIVE is "1" or "true".
14
+ var env_val: String = OS.get_environment("GD_TOOLS_COVERAGE_ACTIVE")
15
+ env_val = env_val.to_lower()
16
+ _active = env_val == "1" or env_val == "true"
17
+
18
+
19
+ func hit(file_id: int, line_id: int) -> void:
20
+ # Single bool check for minimal overhead when inactive.
21
+ if not _active:
22
+ return
23
+ if not _hits.has(file_id):
24
+ _hits[file_id] = {}
25
+ if not _hits[file_id].has(line_id):
26
+ _hits[file_id][line_id] = 0
27
+ _hits[file_id][line_id] += 1
28
+
29
+
30
+ func get_hits() -> Dictionary:
31
+ return _hits
32
+
33
+
34
+ func reset() -> void:
35
+ _hits.clear()
36
+
37
+
38
+ func set_active(active: bool) -> void:
39
+ _active = active
40
+
41
+
42
+ func is_active() -> bool:
43
+ return _active
@@ -0,0 +1,113 @@
1
+ extends GutHookScript
2
+
3
+ ## Post-run hook for GUT test runner.
4
+ ## Collects coverage data from the _GDTCoverage tracker and
5
+ ## writes it to a JSON file after tests have executed.
6
+
7
+ const TRACKER_NAME = "_GDTCoverage"
8
+
9
+
10
+ func run() -> void:
11
+ var tracker = _get_tracker()
12
+ if tracker == null:
13
+ return
14
+
15
+ if not tracker.is_active():
16
+ return
17
+
18
+ var hits: Dictionary = tracker.get_hits()
19
+ var data: Dictionary = _build_coverage_json(hits)
20
+
21
+ var output_path: String = OS.get_environment("GD_TOOLS_COVERAGE_OUTPUT")
22
+ if output_path.is_empty():
23
+ _log_error(
24
+ "Cannot write coverage output.",
25
+ "GD_TOOLS_COVERAGE_OUTPUT environment variable is not set.",
26
+ "Set GD_TOOLS_COVERAGE_OUTPUT to a writable file path."
27
+ )
28
+ return
29
+
30
+ if not _write_json(output_path, data):
31
+ return
32
+
33
+ _log_summary(hits, output_path)
34
+
35
+
36
+ func _get_tracker() -> Node:
37
+ var tree = Engine.get_main_loop() as SceneTree
38
+ if tree == null:
39
+ _log_error(
40
+ "Cannot access coverage tracker.",
41
+ "SceneTree is not available.",
42
+ "Ensure the hook runs in a Godot project context."
43
+ )
44
+ return null
45
+
46
+ var tracker = tree.root.get_node_or_null(TRACKER_NAME)
47
+ if tracker == null:
48
+ _log_error(
49
+ "Cannot access coverage tracker.",
50
+ "Autoload '" + TRACKER_NAME + "' not found.",
51
+ "Ensure the coverage addon is installed and registered as an autoload."
52
+ )
53
+ return null
54
+
55
+ return tracker
56
+
57
+
58
+ func _build_coverage_json(hits: Dictionary) -> Dictionary:
59
+ var files: Array = []
60
+ for file_id in hits:
61
+ var file_hits: Dictionary = hits[file_id]
62
+ var hits_dict: Dictionary = {}
63
+ for line_id in file_hits:
64
+ hits_dict[str(line_id)] = file_hits[line_id]
65
+ files.append({"file_id": int(file_id), "hits": hits_dict})
66
+ return {
67
+ "version": 1,
68
+ "generated_at": Time.get_datetime_string_from_system(true, false) + "Z",
69
+ "files": files
70
+ }
71
+
72
+
73
+ func _write_json(path: String, data: Dictionary) -> bool:
74
+ var dir_path: String = path.get_base_dir()
75
+ if not dir_path.is_empty() and not DirAccess.dir_exists_absolute(dir_path):
76
+ var err: int = DirAccess.make_dir_recursive_absolute(dir_path)
77
+ if err != OK:
78
+ _log_error(
79
+ "Cannot create output directory.",
80
+ "Failed to create directory: " + dir_path,
81
+ "Check permissions and path validity."
82
+ )
83
+ return false
84
+
85
+ var file = FileAccess.open(path, FileAccess.WRITE)
86
+ if file == null:
87
+ _log_error(
88
+ "Cannot write coverage output.",
89
+ "Cannot open file for writing: " + path,
90
+ "Check file permissions and path validity."
91
+ )
92
+ return false
93
+
94
+ file.store_string(JSON.stringify(data, " "))
95
+ file = null
96
+ return true
97
+
98
+
99
+ func _log_summary(hits: Dictionary, output_path: String) -> String:
100
+ var total_files: int = hits.size()
101
+ var total_lines: int = 0
102
+ for file_id in hits:
103
+ total_lines += hits[file_id].size()
104
+ var summary: String = (
105
+ "[gd-tools] Coverage summary: %d files, %d lines tracked, output: %s"
106
+ % [total_files, total_lines, output_path]
107
+ )
108
+ print(summary)
109
+ return summary
110
+
111
+
112
+ func _log_error(what: String, cause: String, fix: String) -> void:
113
+ push_error("[gd-tools] [Error] " + what + "\n\n" + " Cause: " + cause + "\n" + " Fix: " + fix)