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.
- gd_tools_cli-0.1.0/PKG-INFO +191 -0
- gd_tools_cli-0.1.0/README.md +152 -0
- gd_tools_cli-0.1.0/pyproject.toml +96 -0
- gd_tools_cli-0.1.0/setup.cfg +4 -0
- gd_tools_cli-0.1.0/src/gd_tools/__init__.py +3 -0
- gd_tools_cli-0.1.0/src/gd_tools/__main__.py +31 -0
- gd_tools_cli-0.1.0/src/gd_tools/addons/__init__.py +0 -0
- gd_tools_cli-0.1.0/src/gd_tools/addons/gd-tools-coverage/coverage.gd +43 -0
- gd_tools_cli-0.1.0/src/gd_tools/addons/gd-tools-coverage/post_run_hook.gd +113 -0
- gd_tools_cli-0.1.0/src/gd_tools/addons/gd-tools-coverage/pre_run_hook.gd +229 -0
- gd_tools_cli-0.1.0/src/gd_tools/cli.py +329 -0
- gd_tools_cli-0.1.0/src/gd_tools/config.py +289 -0
- gd_tools_cli-0.1.0/src/gd_tools/coverage/__init__.py +23 -0
- gd_tools_cli-0.1.0/src/gd_tools/coverage/cobertura_reporter.py +136 -0
- gd_tools_cli-0.1.0/src/gd_tools/coverage/html_reporter.py +95 -0
- gd_tools_cli-0.1.0/src/gd_tools/coverage/lcov_reporter.py +90 -0
- gd_tools_cli-0.1.0/src/gd_tools/coverage/orchestrator.py +282 -0
- gd_tools_cli-0.1.0/src/gd_tools/coverage/plan_generator.py +377 -0
- gd_tools_cli-0.1.0/src/gd_tools/coverage/reporter.py +518 -0
- gd_tools_cli-0.1.0/src/gd_tools/coverage/templates/file.html +72 -0
- gd_tools_cli-0.1.0/src/gd_tools/coverage/templates/index.html +90 -0
- gd_tools_cli-0.1.0/src/gd_tools/coverage/terminal_reporter.py +107 -0
- gd_tools_cli-0.1.0/src/gd_tools/doctor.py +495 -0
- gd_tools_cli-0.1.0/src/gd_tools/errors.py +79 -0
- gd_tools_cli-0.1.0/src/gd_tools/file_discovery.py +41 -0
- gd_tools_cli-0.1.0/src/gd_tools/format_runner.py +118 -0
- gd_tools_cli-0.1.0/src/gd_tools/godot.py +346 -0
- gd_tools_cli-0.1.0/src/gd_tools/init.py +619 -0
- gd_tools_cli-0.1.0/src/gd_tools/lint_runner.py +223 -0
- gd_tools_cli-0.1.0/src/gd_tools/test_runner.py +474 -0
- gd_tools_cli-0.1.0/src/gd_tools_cli.egg-info/PKG-INFO +191 -0
- gd_tools_cli-0.1.0/src/gd_tools_cli.egg-info/SOURCES.txt +34 -0
- gd_tools_cli-0.1.0/src/gd_tools_cli.egg-info/dependency_links.txt +1 -0
- gd_tools_cli-0.1.0/src/gd_tools_cli.egg-info/entry_points.txt +2 -0
- gd_tools_cli-0.1.0/src/gd_tools_cli.egg-info/requires.txt +18 -0
- 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
|
+
[](https://github.com/mansyar/gd-tools/actions/workflows/ci.yml)
|
|
45
|
+
[](https://codecov.io/gh/mansyar/gd-tools)
|
|
46
|
+
[](https://pypi.org/project/gd-tools/)
|
|
47
|
+
[](https://pypi.org/project/gd-tools/)
|
|
48
|
+
[](https://godotengine.org)
|
|
49
|
+
[](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
|
+
[](https://github.com/mansyar/gd-tools/actions/workflows/ci.yml)
|
|
6
|
+
[](https://codecov.io/gh/mansyar/gd-tools)
|
|
7
|
+
[](https://pypi.org/project/gd-tools/)
|
|
8
|
+
[](https://pypi.org/project/gd-tools/)
|
|
9
|
+
[](https://godotengine.org)
|
|
10
|
+
[](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,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)
|