dbt-tui 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.
- dbt_tui-0.1.0/PKG-INFO +271 -0
- dbt_tui-0.1.0/README.md +243 -0
- dbt_tui-0.1.0/pyproject.toml +58 -0
- dbt_tui-0.1.0/src/dbtui/__init__.py +0 -0
- dbt_tui-0.1.0/src/dbtui/__main__.py +59 -0
- dbt_tui-0.1.0/src/dbtui/backend/__init__.py +2 -0
- dbt_tui-0.1.0/src/dbtui/backend/fetch.py +206 -0
- dbt_tui-0.1.0/src/dbtui/backend/model.py +86 -0
- dbt_tui-0.1.0/src/dbtui/backend/project.py +258 -0
- dbt_tui-0.1.0/src/dbtui/backend/property_claim.py +191 -0
- dbt_tui-0.1.0/src/dbtui/backend/property_discovery.py +461 -0
- dbt_tui-0.1.0/src/dbtui/common/__init__.py +4 -0
- dbt_tui-0.1.0/src/dbtui/common/cache.py +70 -0
- dbt_tui-0.1.0/src/dbtui/common/exceptions.py +14 -0
- dbt_tui-0.1.0/src/dbtui/common/model.py +25 -0
- dbt_tui-0.1.0/src/dbtui/common/project.py +32 -0
- dbt_tui-0.1.0/src/dbtui/frontend/__init__.py +1 -0
- dbt_tui-0.1.0/src/dbtui/frontend/common/__init__.py +4 -0
- dbt_tui-0.1.0/src/dbtui/frontend/common/dbtui_screen.py +50 -0
- dbt_tui-0.1.0/src/dbtui/frontend/common/isolated.py +14 -0
- dbt_tui-0.1.0/src/dbtui/frontend/common/model_list.py +41 -0
- dbt_tui-0.1.0/src/dbtui/frontend/common/model_list_item.py +20 -0
- dbt_tui-0.1.0/src/dbtui/frontend/lorem.txt +9 -0
- dbt_tui-0.1.0/src/dbtui/frontend/main.py +138 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_search/__init__.py +1 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_search/model_search.py +52 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_search/model_search_input.py +21 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_search/model_search_list.py +14 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_tree/__init__.py +1 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_tree/children_list.py +28 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_tree/constants.py +4 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_tree/model_relatives_list.py +15 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_tree/model_tree.py +98 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_tree/parents_list.py +28 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_view/__init__.py +2 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_view/model_tree.py +162 -0
- dbt_tui-0.1.0/src/dbtui/frontend/model_view/properties_panel.py +172 -0
- dbt_tui-0.1.0/src/dbtui/frontend/new_model/__init__.py +1 -0
- dbt_tui-0.1.0/src/dbtui/frontend/new_model/new_model.py +51 -0
- dbt_tui-0.1.0/src/dbtui/frontend/new_model/select_filepath.py +30 -0
- dbt_tui-0.1.0/src/dbtui/frontend/options/__init__.py +1 -0
- dbt_tui-0.1.0/src/dbtui/frontend/options/options.py +37 -0
- dbt_tui-0.1.0/src/dbtui/frontend/project_search/__init__.py +1 -0
- dbt_tui-0.1.0/src/dbtui/frontend/project_search/project_search.py +109 -0
- dbt_tui-0.1.0/src/dbtui/frontend/pseudo/__init__.py +2 -0
- dbt_tui-0.1.0/src/dbtui/frontend/pseudo/dbt_model.py +50 -0
- dbt_tui-0.1.0/src/dbtui/frontend/pseudo/dbt_project.py +37 -0
- dbt_tui-0.1.0/src/dbtui/frontend/pseudo/utils.py +8 -0
dbt_tui-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dbt-tui
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Terminal UI for exploring and managing dbt projects
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: dbt,tui,terminal,data,analytics,sql
|
|
7
|
+
Author: Mike
|
|
8
|
+
Author-email: sortia@protonmail.com
|
|
9
|
+
Requires-Python: >=3.12, <4.0
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Database
|
|
18
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
19
|
+
Requires-Dist: jinja2 (>=3.0)
|
|
20
|
+
Requires-Dist: networkx (>=3.0)
|
|
21
|
+
Requires-Dist: platformdirs (>=4.5.0,<5.0.0)
|
|
22
|
+
Requires-Dist: pyyaml (>=6.0.3,<7.0.0)
|
|
23
|
+
Requires-Dist: textual[syntax] (>=6.5.0,<7.0.0)
|
|
24
|
+
Project-URL: Homepage, https://github.com/sortia/dbt-tui
|
|
25
|
+
Project-URL: Repository, https://github.com/sortia/dbt-tui
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# dbtui
|
|
29
|
+
|
|
30
|
+
A Terminal User Interface (TUI) for navigating and managing [dbt (data build tool)](https://www.getdbt.com/) projects.
|
|
31
|
+
|
|
32
|
+
**dbtui** provides an interactive command-line interface for exploring dbt models, their relationships, and configurations without leaving your terminal.
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
- **Model Explorer**: Browse all models in your dbt project with search capabilities
|
|
37
|
+
- **Dependency Visualization**: View parent and child relationships for any model
|
|
38
|
+
- **Model Preview**: Read model SQL and configuration inline
|
|
39
|
+
- **Quick Navigation**: Jump between related models with keyboard shortcuts
|
|
40
|
+
- **New Model Creation**: Create new models with automatic ref() generation
|
|
41
|
+
- **Property Discovery**: View effective configurations from all sources (dbt_project.yml, schema.yml, model config)
|
|
42
|
+
- **Session Persistence**: Automatically saves and restores your last viewed project and model
|
|
43
|
+
- **External Editor Integration**: Open models in your preferred editor
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
### Requirements
|
|
48
|
+
|
|
49
|
+
- Python 3.12 or higher
|
|
50
|
+
- A dbt project to explore
|
|
51
|
+
|
|
52
|
+
### Install from source
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Clone the repository
|
|
56
|
+
git clone <repository-url>
|
|
57
|
+
cd dbtui
|
|
58
|
+
|
|
59
|
+
# Install dependencies using pip
|
|
60
|
+
pip install -e .
|
|
61
|
+
|
|
62
|
+
# Or using poetry
|
|
63
|
+
poetry install
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Usage
|
|
67
|
+
|
|
68
|
+
### Basic Usage
|
|
69
|
+
|
|
70
|
+
Navigate to a dbt project directory and run:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
python -m dbtui
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Or if installed via poetry:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
poetry run python -m dbtui
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### First Launch
|
|
83
|
+
|
|
84
|
+
On first launch, dbtui will:
|
|
85
|
+
1. Load the test project (if no cached project exists)
|
|
86
|
+
2. Open the model search screen
|
|
87
|
+
3. Allow you to search for and select a model
|
|
88
|
+
|
|
89
|
+
### Keyboard Shortcuts
|
|
90
|
+
|
|
91
|
+
#### Global Bindings
|
|
92
|
+
|
|
93
|
+
| Key | Action | Description |
|
|
94
|
+
|-----|--------|-------------|
|
|
95
|
+
| `o` | Options | Open options/settings screen |
|
|
96
|
+
| `f` | Find Model | Open model search screen |
|
|
97
|
+
| `p` | Project Search | Select a different dbt project |
|
|
98
|
+
| `q` | Quit | Exit the application |
|
|
99
|
+
|
|
100
|
+
#### Model View Screen
|
|
101
|
+
|
|
102
|
+
| Key | Action | Description |
|
|
103
|
+
|-----|--------|-------------|
|
|
104
|
+
| `E` | External Edit | Open current model in external editor |
|
|
105
|
+
| `n` | New Model | Create a new model that refs the current one |
|
|
106
|
+
| `Tab` | Switch Focus | Cycle between parents list, model content, and children list |
|
|
107
|
+
| `↑↓` | Navigate Lists | Move up/down in parent/child lists |
|
|
108
|
+
| `Enter` | Select Model | Navigate to the selected parent/child model |
|
|
109
|
+
|
|
110
|
+
#### Model Search Screen
|
|
111
|
+
|
|
112
|
+
| Key | Action | Description |
|
|
113
|
+
|-----|--------|-------------|
|
|
114
|
+
| Type to search | Live Search | Filter models by name as you type |
|
|
115
|
+
| `↑↓` | Navigate Results | Move through search results |
|
|
116
|
+
| `Enter` | Select Model | Open the selected model |
|
|
117
|
+
|
|
118
|
+
#### New Model Screen
|
|
119
|
+
|
|
120
|
+
| Key | Action | Description |
|
|
121
|
+
|-----|--------|-------------|
|
|
122
|
+
| Type path | Enter Path | Specify relative path for new model (e.g., `models/staging/stg_users.sql`) |
|
|
123
|
+
| `Enter` | Create Model | Create the model and open it |
|
|
124
|
+
| `Esc` | Cancel | Close modal without creating |
|
|
125
|
+
|
|
126
|
+
## Configuration
|
|
127
|
+
|
|
128
|
+
### Cache and Settings
|
|
129
|
+
|
|
130
|
+
dbtui stores its configuration in your system's cache directory:
|
|
131
|
+
|
|
132
|
+
- **Linux**: `~/.cache/dbtui/cache.json`
|
|
133
|
+
- **macOS**: `~/Library/Caches/dbtui/cache.json`
|
|
134
|
+
- **Windows**: `%LOCALAPPDATA%\dbtui\cache.json`
|
|
135
|
+
|
|
136
|
+
The cache stores:
|
|
137
|
+
- Last opened project path
|
|
138
|
+
- Last viewed model
|
|
139
|
+
- External editor command (default: `vi`)
|
|
140
|
+
|
|
141
|
+
### External Editor
|
|
142
|
+
|
|
143
|
+
To configure your preferred external editor, open the options screen (`o` key) and set the editor command. Examples:
|
|
144
|
+
|
|
145
|
+
- `code` - Visual Studio Code
|
|
146
|
+
- `vim` or `vi` - Vim
|
|
147
|
+
- `nano` - Nano
|
|
148
|
+
- `subl` - Sublime Text
|
|
149
|
+
|
|
150
|
+
## Project Structure
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
dbtui/
|
|
154
|
+
├── src/
|
|
155
|
+
│ ├── backend/ # Core dbt project logic
|
|
156
|
+
│ │ ├── project.py # DbtProject class
|
|
157
|
+
│ │ ├── model.py # DbtModel class
|
|
158
|
+
│ │ ├── fetch.py # Property fetching utilities
|
|
159
|
+
│ │ ├── property_claim.py # Property precedence logic
|
|
160
|
+
│ │ └── property_discovery.py # Property discovery from configs
|
|
161
|
+
│ ├── frontend/ # TUI screens and widgets
|
|
162
|
+
│ │ ├── main.py # Main application
|
|
163
|
+
│ │ ├── model_search/ # Model search interface
|
|
164
|
+
│ │ ├── model_tree/ # Model dependency tree view
|
|
165
|
+
│ │ ├── new_model/ # New model creation
|
|
166
|
+
│ │ └── options/ # Settings screen
|
|
167
|
+
│ └── common/ # Shared abstractions and utilities
|
|
168
|
+
│ ├── model.py # Abstract model interface
|
|
169
|
+
│ ├── project.py # Abstract project interface
|
|
170
|
+
│ └── cache.py # Configuration persistence
|
|
171
|
+
├── tests/ # Test suite
|
|
172
|
+
│ └── testing/ # Test dbt project
|
|
173
|
+
└── pyproject.toml # Project dependencies
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Architecture
|
|
177
|
+
|
|
178
|
+
### Backend
|
|
179
|
+
|
|
180
|
+
The backend implements the core dbt project parsing logic:
|
|
181
|
+
|
|
182
|
+
- **DbtProject**: Represents a dbt project, loads models from configured model-paths
|
|
183
|
+
- **DbtModel**: Represents a single model, parses Jinja2 templates to extract refs and configs
|
|
184
|
+
- **PropertyClaim**: Represents a property claim from any configuration source
|
|
185
|
+
- **Property Discovery**: Collects properties from dbt_project.yml, schema.yml, and model SQL
|
|
186
|
+
|
|
187
|
+
### Frontend
|
|
188
|
+
|
|
189
|
+
Built with [Textual](https://textual.textualize.io/), the frontend provides:
|
|
190
|
+
|
|
191
|
+
- **Screen-based navigation**: Each feature is a separate screen
|
|
192
|
+
- **Reactive state management**: Changes to project/model automatically update UI
|
|
193
|
+
- **Keyboard-driven workflow**: All actions accessible via keyboard
|
|
194
|
+
|
|
195
|
+
### Property Precedence
|
|
196
|
+
|
|
197
|
+
dbtui correctly implements dbt's configuration precedence rules:
|
|
198
|
+
|
|
199
|
+
1. **Model-level** (highest): `{{ config(...) }}` in SQL files
|
|
200
|
+
2. **Schema-level**: `config:` blocks in schema.yml
|
|
201
|
+
3. **Project-level** (lowest): `models:` section in dbt_project.yml
|
|
202
|
+
- More specific paths override general ones
|
|
203
|
+
- Example: `models.project.staging.stg_users` > `models.project.staging` > `models.project`
|
|
204
|
+
|
|
205
|
+
## Development
|
|
206
|
+
|
|
207
|
+
### Running Tests
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Run all tests
|
|
211
|
+
pytest
|
|
212
|
+
|
|
213
|
+
# Run specific test file
|
|
214
|
+
pytest tests/test_property_claims.py
|
|
215
|
+
|
|
216
|
+
# Run with coverage
|
|
217
|
+
pytest --cov=src
|
|
218
|
+
|
|
219
|
+
# Run with verbose output
|
|
220
|
+
pytest -v
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Test Project
|
|
224
|
+
|
|
225
|
+
The `tests/testing/` directory contains a sample dbt project used for testing:
|
|
226
|
+
|
|
227
|
+
- Multiple model directories (vanilla, complex_config, invalid)
|
|
228
|
+
- Models with various configurations
|
|
229
|
+
- Schema.yml files with properties and configs
|
|
230
|
+
- Project-level configurations in dbt_project.yml
|
|
231
|
+
|
|
232
|
+
### Adding New Features
|
|
233
|
+
|
|
234
|
+
1. **Backend changes**: Extend DbtProject or DbtModel in `src/backend/`
|
|
235
|
+
2. **Frontend changes**: Create new screens/widgets in `src/frontend/`
|
|
236
|
+
3. **Add tests**: Write tests in `tests/` following existing patterns
|
|
237
|
+
4. **Update abstractions**: Modify `src/common/` interfaces if needed
|
|
238
|
+
|
|
239
|
+
## Roadmap
|
|
240
|
+
|
|
241
|
+
- [ ] Enhanced model search (fuzzy matching, filters)
|
|
242
|
+
- [ ] Property viewer showing all effective configs with sources
|
|
243
|
+
- [ ] DAG visualization (ASCII graph)
|
|
244
|
+
- [ ] Model execution (dbt run, dbt test)
|
|
245
|
+
- [ ] Column-level lineage
|
|
246
|
+
- [ ] Documentation viewer
|
|
247
|
+
- [ ] Git integration
|
|
248
|
+
- [ ] Multiple project workspace
|
|
249
|
+
|
|
250
|
+
## Contributing
|
|
251
|
+
|
|
252
|
+
Contributions are welcome! Please:
|
|
253
|
+
|
|
254
|
+
1. Fork the repository
|
|
255
|
+
2. Create a feature branch
|
|
256
|
+
3. Add tests for new functionality
|
|
257
|
+
4. Ensure all tests pass (`pytest`)
|
|
258
|
+
5. Submit a pull request
|
|
259
|
+
|
|
260
|
+
## License
|
|
261
|
+
|
|
262
|
+
[Add your license here]
|
|
263
|
+
|
|
264
|
+
## Acknowledgments
|
|
265
|
+
|
|
266
|
+
Built with:
|
|
267
|
+
- [Textual](https://textual.textualize.io/) - TUI framework
|
|
268
|
+
- [Jinja2](https://jinja.palletsprojects.com/) - Template parsing
|
|
269
|
+
- [NetworkX](https://networkx.org/) - Graph operations
|
|
270
|
+
- [PyYAML](https://pyyaml.org/) - YAML parsing
|
|
271
|
+
|
dbt_tui-0.1.0/README.md
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# dbtui
|
|
2
|
+
|
|
3
|
+
A Terminal User Interface (TUI) for navigating and managing [dbt (data build tool)](https://www.getdbt.com/) projects.
|
|
4
|
+
|
|
5
|
+
**dbtui** provides an interactive command-line interface for exploring dbt models, their relationships, and configurations without leaving your terminal.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Model Explorer**: Browse all models in your dbt project with search capabilities
|
|
10
|
+
- **Dependency Visualization**: View parent and child relationships for any model
|
|
11
|
+
- **Model Preview**: Read model SQL and configuration inline
|
|
12
|
+
- **Quick Navigation**: Jump between related models with keyboard shortcuts
|
|
13
|
+
- **New Model Creation**: Create new models with automatic ref() generation
|
|
14
|
+
- **Property Discovery**: View effective configurations from all sources (dbt_project.yml, schema.yml, model config)
|
|
15
|
+
- **Session Persistence**: Automatically saves and restores your last viewed project and model
|
|
16
|
+
- **External Editor Integration**: Open models in your preferred editor
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
### Requirements
|
|
21
|
+
|
|
22
|
+
- Python 3.12 or higher
|
|
23
|
+
- A dbt project to explore
|
|
24
|
+
|
|
25
|
+
### Install from source
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Clone the repository
|
|
29
|
+
git clone <repository-url>
|
|
30
|
+
cd dbtui
|
|
31
|
+
|
|
32
|
+
# Install dependencies using pip
|
|
33
|
+
pip install -e .
|
|
34
|
+
|
|
35
|
+
# Or using poetry
|
|
36
|
+
poetry install
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
### Basic Usage
|
|
42
|
+
|
|
43
|
+
Navigate to a dbt project directory and run:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
python -m dbtui
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Or if installed via poetry:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
poetry run python -m dbtui
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### First Launch
|
|
56
|
+
|
|
57
|
+
On first launch, dbtui will:
|
|
58
|
+
1. Load the test project (if no cached project exists)
|
|
59
|
+
2. Open the model search screen
|
|
60
|
+
3. Allow you to search for and select a model
|
|
61
|
+
|
|
62
|
+
### Keyboard Shortcuts
|
|
63
|
+
|
|
64
|
+
#### Global Bindings
|
|
65
|
+
|
|
66
|
+
| Key | Action | Description |
|
|
67
|
+
|-----|--------|-------------|
|
|
68
|
+
| `o` | Options | Open options/settings screen |
|
|
69
|
+
| `f` | Find Model | Open model search screen |
|
|
70
|
+
| `p` | Project Search | Select a different dbt project |
|
|
71
|
+
| `q` | Quit | Exit the application |
|
|
72
|
+
|
|
73
|
+
#### Model View Screen
|
|
74
|
+
|
|
75
|
+
| Key | Action | Description |
|
|
76
|
+
|-----|--------|-------------|
|
|
77
|
+
| `E` | External Edit | Open current model in external editor |
|
|
78
|
+
| `n` | New Model | Create a new model that refs the current one |
|
|
79
|
+
| `Tab` | Switch Focus | Cycle between parents list, model content, and children list |
|
|
80
|
+
| `↑↓` | Navigate Lists | Move up/down in parent/child lists |
|
|
81
|
+
| `Enter` | Select Model | Navigate to the selected parent/child model |
|
|
82
|
+
|
|
83
|
+
#### Model Search Screen
|
|
84
|
+
|
|
85
|
+
| Key | Action | Description |
|
|
86
|
+
|-----|--------|-------------|
|
|
87
|
+
| Type to search | Live Search | Filter models by name as you type |
|
|
88
|
+
| `↑↓` | Navigate Results | Move through search results |
|
|
89
|
+
| `Enter` | Select Model | Open the selected model |
|
|
90
|
+
|
|
91
|
+
#### New Model Screen
|
|
92
|
+
|
|
93
|
+
| Key | Action | Description |
|
|
94
|
+
|-----|--------|-------------|
|
|
95
|
+
| Type path | Enter Path | Specify relative path for new model (e.g., `models/staging/stg_users.sql`) |
|
|
96
|
+
| `Enter` | Create Model | Create the model and open it |
|
|
97
|
+
| `Esc` | Cancel | Close modal without creating |
|
|
98
|
+
|
|
99
|
+
## Configuration
|
|
100
|
+
|
|
101
|
+
### Cache and Settings
|
|
102
|
+
|
|
103
|
+
dbtui stores its configuration in your system's cache directory:
|
|
104
|
+
|
|
105
|
+
- **Linux**: `~/.cache/dbtui/cache.json`
|
|
106
|
+
- **macOS**: `~/Library/Caches/dbtui/cache.json`
|
|
107
|
+
- **Windows**: `%LOCALAPPDATA%\dbtui\cache.json`
|
|
108
|
+
|
|
109
|
+
The cache stores:
|
|
110
|
+
- Last opened project path
|
|
111
|
+
- Last viewed model
|
|
112
|
+
- External editor command (default: `vi`)
|
|
113
|
+
|
|
114
|
+
### External Editor
|
|
115
|
+
|
|
116
|
+
To configure your preferred external editor, open the options screen (`o` key) and set the editor command. Examples:
|
|
117
|
+
|
|
118
|
+
- `code` - Visual Studio Code
|
|
119
|
+
- `vim` or `vi` - Vim
|
|
120
|
+
- `nano` - Nano
|
|
121
|
+
- `subl` - Sublime Text
|
|
122
|
+
|
|
123
|
+
## Project Structure
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
dbtui/
|
|
127
|
+
├── src/
|
|
128
|
+
│ ├── backend/ # Core dbt project logic
|
|
129
|
+
│ │ ├── project.py # DbtProject class
|
|
130
|
+
│ │ ├── model.py # DbtModel class
|
|
131
|
+
│ │ ├── fetch.py # Property fetching utilities
|
|
132
|
+
│ │ ├── property_claim.py # Property precedence logic
|
|
133
|
+
│ │ └── property_discovery.py # Property discovery from configs
|
|
134
|
+
│ ├── frontend/ # TUI screens and widgets
|
|
135
|
+
│ │ ├── main.py # Main application
|
|
136
|
+
│ │ ├── model_search/ # Model search interface
|
|
137
|
+
│ │ ├── model_tree/ # Model dependency tree view
|
|
138
|
+
│ │ ├── new_model/ # New model creation
|
|
139
|
+
│ │ └── options/ # Settings screen
|
|
140
|
+
│ └── common/ # Shared abstractions and utilities
|
|
141
|
+
│ ├── model.py # Abstract model interface
|
|
142
|
+
│ ├── project.py # Abstract project interface
|
|
143
|
+
│ └── cache.py # Configuration persistence
|
|
144
|
+
├── tests/ # Test suite
|
|
145
|
+
│ └── testing/ # Test dbt project
|
|
146
|
+
└── pyproject.toml # Project dependencies
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Architecture
|
|
150
|
+
|
|
151
|
+
### Backend
|
|
152
|
+
|
|
153
|
+
The backend implements the core dbt project parsing logic:
|
|
154
|
+
|
|
155
|
+
- **DbtProject**: Represents a dbt project, loads models from configured model-paths
|
|
156
|
+
- **DbtModel**: Represents a single model, parses Jinja2 templates to extract refs and configs
|
|
157
|
+
- **PropertyClaim**: Represents a property claim from any configuration source
|
|
158
|
+
- **Property Discovery**: Collects properties from dbt_project.yml, schema.yml, and model SQL
|
|
159
|
+
|
|
160
|
+
### Frontend
|
|
161
|
+
|
|
162
|
+
Built with [Textual](https://textual.textualize.io/), the frontend provides:
|
|
163
|
+
|
|
164
|
+
- **Screen-based navigation**: Each feature is a separate screen
|
|
165
|
+
- **Reactive state management**: Changes to project/model automatically update UI
|
|
166
|
+
- **Keyboard-driven workflow**: All actions accessible via keyboard
|
|
167
|
+
|
|
168
|
+
### Property Precedence
|
|
169
|
+
|
|
170
|
+
dbtui correctly implements dbt's configuration precedence rules:
|
|
171
|
+
|
|
172
|
+
1. **Model-level** (highest): `{{ config(...) }}` in SQL files
|
|
173
|
+
2. **Schema-level**: `config:` blocks in schema.yml
|
|
174
|
+
3. **Project-level** (lowest): `models:` section in dbt_project.yml
|
|
175
|
+
- More specific paths override general ones
|
|
176
|
+
- Example: `models.project.staging.stg_users` > `models.project.staging` > `models.project`
|
|
177
|
+
|
|
178
|
+
## Development
|
|
179
|
+
|
|
180
|
+
### Running Tests
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Run all tests
|
|
184
|
+
pytest
|
|
185
|
+
|
|
186
|
+
# Run specific test file
|
|
187
|
+
pytest tests/test_property_claims.py
|
|
188
|
+
|
|
189
|
+
# Run with coverage
|
|
190
|
+
pytest --cov=src
|
|
191
|
+
|
|
192
|
+
# Run with verbose output
|
|
193
|
+
pytest -v
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Test Project
|
|
197
|
+
|
|
198
|
+
The `tests/testing/` directory contains a sample dbt project used for testing:
|
|
199
|
+
|
|
200
|
+
- Multiple model directories (vanilla, complex_config, invalid)
|
|
201
|
+
- Models with various configurations
|
|
202
|
+
- Schema.yml files with properties and configs
|
|
203
|
+
- Project-level configurations in dbt_project.yml
|
|
204
|
+
|
|
205
|
+
### Adding New Features
|
|
206
|
+
|
|
207
|
+
1. **Backend changes**: Extend DbtProject or DbtModel in `src/backend/`
|
|
208
|
+
2. **Frontend changes**: Create new screens/widgets in `src/frontend/`
|
|
209
|
+
3. **Add tests**: Write tests in `tests/` following existing patterns
|
|
210
|
+
4. **Update abstractions**: Modify `src/common/` interfaces if needed
|
|
211
|
+
|
|
212
|
+
## Roadmap
|
|
213
|
+
|
|
214
|
+
- [ ] Enhanced model search (fuzzy matching, filters)
|
|
215
|
+
- [ ] Property viewer showing all effective configs with sources
|
|
216
|
+
- [ ] DAG visualization (ASCII graph)
|
|
217
|
+
- [ ] Model execution (dbt run, dbt test)
|
|
218
|
+
- [ ] Column-level lineage
|
|
219
|
+
- [ ] Documentation viewer
|
|
220
|
+
- [ ] Git integration
|
|
221
|
+
- [ ] Multiple project workspace
|
|
222
|
+
|
|
223
|
+
## Contributing
|
|
224
|
+
|
|
225
|
+
Contributions are welcome! Please:
|
|
226
|
+
|
|
227
|
+
1. Fork the repository
|
|
228
|
+
2. Create a feature branch
|
|
229
|
+
3. Add tests for new functionality
|
|
230
|
+
4. Ensure all tests pass (`pytest`)
|
|
231
|
+
5. Submit a pull request
|
|
232
|
+
|
|
233
|
+
## License
|
|
234
|
+
|
|
235
|
+
[Add your license here]
|
|
236
|
+
|
|
237
|
+
## Acknowledgments
|
|
238
|
+
|
|
239
|
+
Built with:
|
|
240
|
+
- [Textual](https://textual.textualize.io/) - TUI framework
|
|
241
|
+
- [Jinja2](https://jinja.palletsprojects.com/) - Template parsing
|
|
242
|
+
- [NetworkX](https://networkx.org/) - Graph operations
|
|
243
|
+
- [PyYAML](https://pyyaml.org/) - YAML parsing
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "dbt-tui"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Terminal UI for exploring and managing dbt projects"
|
|
5
|
+
authors = [
|
|
6
|
+
{name = "Mike", email = "sortia@protonmail.com"}
|
|
7
|
+
]
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
license = {text = "MIT"}
|
|
10
|
+
requires-python = ">=3.12, <4.0"
|
|
11
|
+
keywords = ["dbt", "tui", "terminal", "data", "analytics", "sql"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Environment :: Console",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Topic :: Database",
|
|
21
|
+
"Topic :: Software Development :: User Interfaces",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"pyyaml>=6.0.3,<7.0.0",
|
|
25
|
+
"textual[syntax]>=6.5.0,<7.0.0",
|
|
26
|
+
"platformdirs>=4.5.0,<5.0.0",
|
|
27
|
+
"networkx>=3.0",
|
|
28
|
+
"jinja2>=3.0",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/sortia/dbt-tui"
|
|
33
|
+
Repository = "https://github.com/sortia/dbt-tui"
|
|
34
|
+
|
|
35
|
+
[project.scripts]
|
|
36
|
+
dbt-tui = "dbtui.__main__:main"
|
|
37
|
+
dbtui = "dbtui.__main__:main"
|
|
38
|
+
|
|
39
|
+
[tool.poetry]
|
|
40
|
+
packages = [{include = "dbtui", from = "src"}]
|
|
41
|
+
|
|
42
|
+
[tool.poetry.group.dev.dependencies]
|
|
43
|
+
pytest = "^9.0.0"
|
|
44
|
+
pytest-asyncio = "^1.0.0"
|
|
45
|
+
|
|
46
|
+
[build-system]
|
|
47
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
48
|
+
build-backend = "poetry.core.masonry.api"
|
|
49
|
+
|
|
50
|
+
[tool.pytest.ini_options]
|
|
51
|
+
filterwarnings = [
|
|
52
|
+
"ignore::DeprecationWarning",
|
|
53
|
+
]
|
|
54
|
+
testpaths = [
|
|
55
|
+
"tests",
|
|
56
|
+
]
|
|
57
|
+
asyncio_mode = "auto"
|
|
58
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
File without changes
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""
|
|
2
|
+
dbtui - Terminal UI for dbt projects
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
python -m dbtui [project_dir]
|
|
6
|
+
|
|
7
|
+
If project_dir is not specified, launches with the last opened project.
|
|
8
|
+
"""
|
|
9
|
+
import argparse
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from .frontend import frontend as dbtuiFrontend
|
|
14
|
+
from .common import load_cache, save_cache
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def main():
|
|
18
|
+
parser = argparse.ArgumentParser(
|
|
19
|
+
prog='dbtui',
|
|
20
|
+
description='Terminal UI for exploring and managing dbt projects'
|
|
21
|
+
)
|
|
22
|
+
parser.add_argument(
|
|
23
|
+
'project_dir',
|
|
24
|
+
nargs='?',
|
|
25
|
+
default=None,
|
|
26
|
+
help='Path to dbt project directory (optional, uses last project if not specified)'
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
args = parser.parse_args()
|
|
30
|
+
|
|
31
|
+
# If project_dir is provided, validate it and save to cache
|
|
32
|
+
if args.project_dir:
|
|
33
|
+
project_path = Path(args.project_dir).resolve()
|
|
34
|
+
|
|
35
|
+
if not project_path.exists():
|
|
36
|
+
print(f"Error: Directory not found: {project_path}", file=sys.stderr)
|
|
37
|
+
sys.exit(1)
|
|
38
|
+
|
|
39
|
+
if not (project_path / 'dbt_project.yml').exists():
|
|
40
|
+
print(f"Error: Not a dbt project (no dbt_project.yml found): {project_path}", file=sys.stderr)
|
|
41
|
+
sys.exit(1)
|
|
42
|
+
|
|
43
|
+
# Load existing cache to preserve external_editor_command
|
|
44
|
+
existing_cache = load_cache()
|
|
45
|
+
|
|
46
|
+
# Save the project path to cache so the app loads it
|
|
47
|
+
save_cache(
|
|
48
|
+
project_path=project_path,
|
|
49
|
+
model_name=None,
|
|
50
|
+
external_editor_command=existing_cache.external_editor_command
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Launch the app
|
|
54
|
+
app = dbtuiFrontend()
|
|
55
|
+
app.run()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
if __name__ == '__main__':
|
|
59
|
+
main()
|