dashiyaml 0.0.2__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.
- dashiyaml-0.0.2/LICENSE +21 -0
- dashiyaml-0.0.2/PKG-INFO +184 -0
- dashiyaml-0.0.2/README.md +150 -0
- dashiyaml-0.0.2/pyproject.toml +50 -0
- dashiyaml-0.0.2/setup.cfg +4 -0
- dashiyaml-0.0.2/src/dashi/__init__.py +1 -0
- dashiyaml-0.0.2/src/dashi/charts/__init__.py +6 -0
- dashiyaml-0.0.2/src/dashi/charts/bar.py +18 -0
- dashiyaml-0.0.2/src/dashi/charts/chart.py +23 -0
- dashiyaml-0.0.2/src/dashi/charts/line.py +18 -0
- dashiyaml-0.0.2/src/dashi/charts/pie.py +20 -0
- dashiyaml-0.0.2/src/dashi/charts/registry.py +13 -0
- dashiyaml-0.0.2/src/dashi/charts/scatter.py +19 -0
- dashiyaml-0.0.2/src/dashi/charts/table.py +13 -0
- dashiyaml-0.0.2/src/dashi/cli.py +61 -0
- dashiyaml-0.0.2/src/dashi/config/__init__.py +1 -0
- dashiyaml-0.0.2/src/dashi/config/yaml_parser.py +43 -0
- dashiyaml-0.0.2/src/dashi/dashboard.py +88 -0
- dashiyaml-0.0.2/src/dashi/datasources/__init__.py +6 -0
- dashiyaml-0.0.2/src/dashi/datasources/base_datasource.py +18 -0
- dashiyaml-0.0.2/src/dashi/datasources/csv_datasource.py +10 -0
- dashiyaml-0.0.2/src/dashi/datasources/datasources.py +40 -0
- dashiyaml-0.0.2/src/dashi/datasources/duckdb_datasource.py +15 -0
- dashiyaml-0.0.2/src/dashi/datasources/file_datasource.py +44 -0
- dashiyaml-0.0.2/src/dashi/datasources/json_datasource.py +9 -0
- dashiyaml-0.0.2/src/dashi/datasources/login_mixin.py +21 -0
- dashiyaml-0.0.2/src/dashi/datasources/postgres_datasource.py +59 -0
- dashiyaml-0.0.2/src/dashi/datasources/registry.py +12 -0
- dashiyaml-0.0.2/src/dashi/datasources/sql_datasource.py +12 -0
- dashiyaml-0.0.2/src/dashi/helpers.py +2 -0
- dashiyaml-0.0.2/src/dashi/render.py +13 -0
- dashiyaml-0.0.2/src/dashi/serve.py +16 -0
- dashiyaml-0.0.2/src/dashi/structure/__init__.py +0 -0
- dashiyaml-0.0.2/src/dashi/structure/cleaner.py +10 -0
- dashiyaml-0.0.2/src/dashi/structure/initializer.py +139 -0
- dashiyaml-0.0.2/src/dashi/transforms/__init__.py +0 -0
- dashiyaml-0.0.2/src/dashi/transforms/transforms.py +31 -0
- dashiyaml-0.0.2/src/dashiyaml.egg-info/PKG-INFO +184 -0
- dashiyaml-0.0.2/src/dashiyaml.egg-info/SOURCES.txt +47 -0
- dashiyaml-0.0.2/src/dashiyaml.egg-info/dependency_links.txt +1 -0
- dashiyaml-0.0.2/src/dashiyaml.egg-info/entry_points.txt +2 -0
- dashiyaml-0.0.2/src/dashiyaml.egg-info/requires.txt +10 -0
- dashiyaml-0.0.2/src/dashiyaml.egg-info/top_level.txt +1 -0
- dashiyaml-0.0.2/tests/test_charts.py +118 -0
- dashiyaml-0.0.2/tests/test_datasources.py +74 -0
- dashiyaml-0.0.2/tests/test_helpers.py +6 -0
- dashiyaml-0.0.2/tests/test_parser.py +8 -0
- dashiyaml-0.0.2/tests/test_sqldatasources.py +41 -0
- dashiyaml-0.0.2/tests/test_transforms.py +62 -0
dashiyaml-0.0.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Corentin Dupriez
|
|
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.
|
dashiyaml-0.0.2/PKG-INFO
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dashiyaml
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: Dashboard as code tool - turn YAML configs into standalone HTML dashboards
|
|
5
|
+
Author: Corentin Dupriez
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Corentin-dupriez/dashi
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/Corentin-dupriez/dashi/issues
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: polars
|
|
25
|
+
Requires-Dist: plotly
|
|
26
|
+
Requires-Dist: numpy
|
|
27
|
+
Requires-Dist: pyyaml
|
|
28
|
+
Requires-Dist: jinja2
|
|
29
|
+
Requires-Dist: typer
|
|
30
|
+
Requires-Dist: duckdb
|
|
31
|
+
Provides-Extra: postgres
|
|
32
|
+
Requires-Dist: psycopg2-binary; extra == "postgres"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# dashi
|
|
36
|
+
|
|
37
|
+
dashi is a dashboard-as-code application that allows you to create dashboards
|
|
38
|
+
from yaml files. It used Polars for fast and efficient dataframe processing,
|
|
39
|
+
and Plotly for visualisation.
|
|
40
|
+
|
|
41
|
+
## Status
|
|
42
|
+
|
|
43
|
+
⚠️ dashi is currently in early development.
|
|
44
|
+
The API and configuration format may change.
|
|
45
|
+
|
|
46
|
+
## Philosophy
|
|
47
|
+
|
|
48
|
+
dashi follows a **dashboard-as-code** approach.
|
|
49
|
+
|
|
50
|
+
Instead of building dashboards through a GUI, dashboards are defined
|
|
51
|
+
as YAML files that can be versioned, reviewed, and deployed like code.
|
|
52
|
+
|
|
53
|
+
This allows dashboards to be:
|
|
54
|
+
|
|
55
|
+
- version controlled
|
|
56
|
+
- reproducible
|
|
57
|
+
- easy to review in pull requests
|
|
58
|
+
|
|
59
|
+
## How to use
|
|
60
|
+
|
|
61
|
+
### Install Dashi
|
|
62
|
+
|
|
63
|
+
First, make sure Python 3.9 or above is installed:
|
|
64
|
+
`python --version`
|
|
65
|
+
|
|
66
|
+
Install dashi from Pypi:
|
|
67
|
+
`pip install dashiyaml`
|
|
68
|
+
|
|
69
|
+
For PostgreSQL datasource support, install the optional extra:
|
|
70
|
+
`pip install dashi[postgres]`
|
|
71
|
+
|
|
72
|
+
### Initialize folder structure
|
|
73
|
+
|
|
74
|
+
After having cloned the repo and installed dependencies, you can initiate the
|
|
75
|
+
folder structure with
|
|
76
|
+
|
|
77
|
+
`dashi init`
|
|
78
|
+
|
|
79
|
+
This will create the following structure (if it doesn't already exist)
|
|
80
|
+
|
|
81
|
+
```txt
|
|
82
|
+
+ data_sources
|
|
83
|
+
+ staging_data
|
|
84
|
+
+ templates
|
|
85
|
+
+ dashboard_template.html
|
|
86
|
+
+ builds
|
|
87
|
+
+ static
|
|
88
|
+
+ style.css
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Configuring data sources
|
|
92
|
+
|
|
93
|
+
The first step of creating visualisations is done by defining data sources.
|
|
94
|
+
This should be done in the data_sources folder as a yaml file. This file
|
|
95
|
+
should contain the parametrization listed below.
|
|
96
|
+
|
|
97
|
+
#### Csv and JSON datasources
|
|
98
|
+
|
|
99
|
+
Csv and JSON
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
datasources:
|
|
103
|
+
- name: sample_data
|
|
104
|
+
type: csv
|
|
105
|
+
columns:
|
|
106
|
+
- name: id
|
|
107
|
+
type: integer
|
|
108
|
+
- name: name
|
|
109
|
+
type: string
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
For the moment, only the csv, json, duckdb and PostgreSQL datasource types are supported,
|
|
113
|
+
but more formats will be supported soon.
|
|
114
|
+
The datasource name must match the filename (without the extension)
|
|
115
|
+
of the data file stored in the `staging_data` folder.
|
|
116
|
+
When using the `dashi build` command, dashi
|
|
117
|
+
will then look within the staging_data folder, and generate a polars dataframe
|
|
118
|
+
by using the defined schema.
|
|
119
|
+
|
|
120
|
+
### Configuring the dashboards
|
|
121
|
+
|
|
122
|
+
Once the datasources are defined, the dashboard itself can be defined within the
|
|
123
|
+
`dashboards` folder as a yaml file. Each yaml file should correspond to
|
|
124
|
+
one dashboard, but each dashboard is composed of several charts.
|
|
125
|
+
The file should contain the dashboard name, as well as a list of charts.
|
|
126
|
+
Each chart should be defined with:
|
|
127
|
+
|
|
128
|
+
- title
|
|
129
|
+
- chart type (ex: line, bar)
|
|
130
|
+
- datasource (corresponding to a datasource defined in `data_sources`)
|
|
131
|
+
- x (corresponding to a column defined for the datasource)
|
|
132
|
+
- y (corresponding to a column defined for the datasource)
|
|
133
|
+
- options: allow a pass through of plotly options to the widget. For example:
|
|
134
|
+
- theme
|
|
135
|
+
- title
|
|
136
|
+
- font
|
|
137
|
+
- transforms: contains instructions on transformation of the data before plotting.
|
|
138
|
+
This includes:
|
|
139
|
+
- group by
|
|
140
|
+
- sum
|
|
141
|
+
- average
|
|
142
|
+
- count
|
|
143
|
+
|
|
144
|
+
All the options that can be passed can be seen [on the Plotly documentation](https://plotly.com/python/reference/layout/)
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
dashboard:
|
|
148
|
+
title: sample_dashboard
|
|
149
|
+
|
|
150
|
+
charts:
|
|
151
|
+
- name: sample_chart
|
|
152
|
+
type: bar
|
|
153
|
+
datasource: sample_data
|
|
154
|
+
x: channel
|
|
155
|
+
y: orders
|
|
156
|
+
options:
|
|
157
|
+
title: Orders by channel
|
|
158
|
+
template: plotly_white
|
|
159
|
+
transform:
|
|
160
|
+
groupby: channel
|
|
161
|
+
metrics:
|
|
162
|
+
orders: sum
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### dashi build
|
|
167
|
+
|
|
168
|
+
Once both datasources and dashboards have been defined, the `dashi build`
|
|
169
|
+
command can be used to create the dashboards based on the provided definitions.
|
|
170
|
+
|
|
171
|
+
This command will create html files under the `builds` folder.
|
|
172
|
+
|
|
173
|
+
WARNING: `dashi build` will override previous version of the dashboards
|
|
174
|
+
you have already exported
|
|
175
|
+
|
|
176
|
+
### dashi serve
|
|
177
|
+
|
|
178
|
+
The command `dashi serve` will create a simple http server on the port 8000
|
|
179
|
+
by default. The created dashboards can be accessed from there.
|
|
180
|
+
|
|
181
|
+
### dashi clean
|
|
182
|
+
|
|
183
|
+
If you wish to clean up the created dashboards, you can use the `dashi clean` command.
|
|
184
|
+
It will delete every html file within the `builds` folder
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# dashi
|
|
2
|
+
|
|
3
|
+
dashi is a dashboard-as-code application that allows you to create dashboards
|
|
4
|
+
from yaml files. It used Polars for fast and efficient dataframe processing,
|
|
5
|
+
and Plotly for visualisation.
|
|
6
|
+
|
|
7
|
+
## Status
|
|
8
|
+
|
|
9
|
+
⚠️ dashi is currently in early development.
|
|
10
|
+
The API and configuration format may change.
|
|
11
|
+
|
|
12
|
+
## Philosophy
|
|
13
|
+
|
|
14
|
+
dashi follows a **dashboard-as-code** approach.
|
|
15
|
+
|
|
16
|
+
Instead of building dashboards through a GUI, dashboards are defined
|
|
17
|
+
as YAML files that can be versioned, reviewed, and deployed like code.
|
|
18
|
+
|
|
19
|
+
This allows dashboards to be:
|
|
20
|
+
|
|
21
|
+
- version controlled
|
|
22
|
+
- reproducible
|
|
23
|
+
- easy to review in pull requests
|
|
24
|
+
|
|
25
|
+
## How to use
|
|
26
|
+
|
|
27
|
+
### Install Dashi
|
|
28
|
+
|
|
29
|
+
First, make sure Python 3.9 or above is installed:
|
|
30
|
+
`python --version`
|
|
31
|
+
|
|
32
|
+
Install dashi from Pypi:
|
|
33
|
+
`pip install dashiyaml`
|
|
34
|
+
|
|
35
|
+
For PostgreSQL datasource support, install the optional extra:
|
|
36
|
+
`pip install dashi[postgres]`
|
|
37
|
+
|
|
38
|
+
### Initialize folder structure
|
|
39
|
+
|
|
40
|
+
After having cloned the repo and installed dependencies, you can initiate the
|
|
41
|
+
folder structure with
|
|
42
|
+
|
|
43
|
+
`dashi init`
|
|
44
|
+
|
|
45
|
+
This will create the following structure (if it doesn't already exist)
|
|
46
|
+
|
|
47
|
+
```txt
|
|
48
|
+
+ data_sources
|
|
49
|
+
+ staging_data
|
|
50
|
+
+ templates
|
|
51
|
+
+ dashboard_template.html
|
|
52
|
+
+ builds
|
|
53
|
+
+ static
|
|
54
|
+
+ style.css
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Configuring data sources
|
|
58
|
+
|
|
59
|
+
The first step of creating visualisations is done by defining data sources.
|
|
60
|
+
This should be done in the data_sources folder as a yaml file. This file
|
|
61
|
+
should contain the parametrization listed below.
|
|
62
|
+
|
|
63
|
+
#### Csv and JSON datasources
|
|
64
|
+
|
|
65
|
+
Csv and JSON
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
datasources:
|
|
69
|
+
- name: sample_data
|
|
70
|
+
type: csv
|
|
71
|
+
columns:
|
|
72
|
+
- name: id
|
|
73
|
+
type: integer
|
|
74
|
+
- name: name
|
|
75
|
+
type: string
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
For the moment, only the csv, json, duckdb and PostgreSQL datasource types are supported,
|
|
79
|
+
but more formats will be supported soon.
|
|
80
|
+
The datasource name must match the filename (without the extension)
|
|
81
|
+
of the data file stored in the `staging_data` folder.
|
|
82
|
+
When using the `dashi build` command, dashi
|
|
83
|
+
will then look within the staging_data folder, and generate a polars dataframe
|
|
84
|
+
by using the defined schema.
|
|
85
|
+
|
|
86
|
+
### Configuring the dashboards
|
|
87
|
+
|
|
88
|
+
Once the datasources are defined, the dashboard itself can be defined within the
|
|
89
|
+
`dashboards` folder as a yaml file. Each yaml file should correspond to
|
|
90
|
+
one dashboard, but each dashboard is composed of several charts.
|
|
91
|
+
The file should contain the dashboard name, as well as a list of charts.
|
|
92
|
+
Each chart should be defined with:
|
|
93
|
+
|
|
94
|
+
- title
|
|
95
|
+
- chart type (ex: line, bar)
|
|
96
|
+
- datasource (corresponding to a datasource defined in `data_sources`)
|
|
97
|
+
- x (corresponding to a column defined for the datasource)
|
|
98
|
+
- y (corresponding to a column defined for the datasource)
|
|
99
|
+
- options: allow a pass through of plotly options to the widget. For example:
|
|
100
|
+
- theme
|
|
101
|
+
- title
|
|
102
|
+
- font
|
|
103
|
+
- transforms: contains instructions on transformation of the data before plotting.
|
|
104
|
+
This includes:
|
|
105
|
+
- group by
|
|
106
|
+
- sum
|
|
107
|
+
- average
|
|
108
|
+
- count
|
|
109
|
+
|
|
110
|
+
All the options that can be passed can be seen [on the Plotly documentation](https://plotly.com/python/reference/layout/)
|
|
111
|
+
|
|
112
|
+
```yaml
|
|
113
|
+
dashboard:
|
|
114
|
+
title: sample_dashboard
|
|
115
|
+
|
|
116
|
+
charts:
|
|
117
|
+
- name: sample_chart
|
|
118
|
+
type: bar
|
|
119
|
+
datasource: sample_data
|
|
120
|
+
x: channel
|
|
121
|
+
y: orders
|
|
122
|
+
options:
|
|
123
|
+
title: Orders by channel
|
|
124
|
+
template: plotly_white
|
|
125
|
+
transform:
|
|
126
|
+
groupby: channel
|
|
127
|
+
metrics:
|
|
128
|
+
orders: sum
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### dashi build
|
|
133
|
+
|
|
134
|
+
Once both datasources and dashboards have been defined, the `dashi build`
|
|
135
|
+
command can be used to create the dashboards based on the provided definitions.
|
|
136
|
+
|
|
137
|
+
This command will create html files under the `builds` folder.
|
|
138
|
+
|
|
139
|
+
WARNING: `dashi build` will override previous version of the dashboards
|
|
140
|
+
you have already exported
|
|
141
|
+
|
|
142
|
+
### dashi serve
|
|
143
|
+
|
|
144
|
+
The command `dashi serve` will create a simple http server on the port 8000
|
|
145
|
+
by default. The created dashboards can be accessed from there.
|
|
146
|
+
|
|
147
|
+
### dashi clean
|
|
148
|
+
|
|
149
|
+
If you wish to clean up the created dashboards, you can use the `dashi clean` command.
|
|
150
|
+
It will delete every html file within the `builds` folder
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "dashiyaml"
|
|
7
|
+
version = "0.0.2"
|
|
8
|
+
description = "Dashboard as code tool - turn YAML configs into standalone HTML dashboards"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Corentin Dupriez" }]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 3 - Alpha",
|
|
15
|
+
"Environment :: Console",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Intended Audience :: Science/Research",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.9",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
25
|
+
"Topic :: Utilities",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"polars",
|
|
29
|
+
"plotly",
|
|
30
|
+
"numpy",
|
|
31
|
+
"pyyaml",
|
|
32
|
+
"jinja2",
|
|
33
|
+
"typer",
|
|
34
|
+
"duckdb",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
postgres = ["psycopg2-binary"]
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://github.com/Corentin-dupriez/dashi"
|
|
42
|
+
"Bug Tracker" = "https://github.com/Corentin-dupriez/dashi/issues"
|
|
43
|
+
|
|
44
|
+
[project.scripts]
|
|
45
|
+
dashi = "dashi.cli:app"
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.packages.find]
|
|
48
|
+
where = ["src"]
|
|
49
|
+
include = ["dashi*"]
|
|
50
|
+
exclude = ["tests*"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.1"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .chart import BaseChart
|
|
2
|
+
import plotly.express as px
|
|
3
|
+
import polars as pl
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BarChart(BaseChart):
|
|
7
|
+
def build(
|
|
8
|
+
self,
|
|
9
|
+
chart_name: str,
|
|
10
|
+
df: pl.DataFrame,
|
|
11
|
+
x: str,
|
|
12
|
+
y: str,
|
|
13
|
+
options: dict[str, str] | None = None,
|
|
14
|
+
):
|
|
15
|
+
fig = px.bar(data_frame=df, x=x, y=y, title=chart_name)
|
|
16
|
+
if options is not None:
|
|
17
|
+
self.update_layout(fig, options)
|
|
18
|
+
return fig
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import polars as pl
|
|
2
|
+
from abc import ABC
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class BaseChart(ABC):
|
|
6
|
+
def build(
|
|
7
|
+
self,
|
|
8
|
+
chart_name: str,
|
|
9
|
+
df: pl.DataFrame,
|
|
10
|
+
x: str,
|
|
11
|
+
y: str,
|
|
12
|
+
options: dict[str, str] | None,
|
|
13
|
+
):
|
|
14
|
+
raise NotImplementedError
|
|
15
|
+
|
|
16
|
+
def update_layout(self, fig, options: dict):
|
|
17
|
+
try:
|
|
18
|
+
fig.update_layout(**options)
|
|
19
|
+
return fig
|
|
20
|
+
except ValueError:
|
|
21
|
+
raise ValueError(
|
|
22
|
+
"One of the options provided in the chart definition is incorrect"
|
|
23
|
+
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .chart import BaseChart
|
|
2
|
+
import polars as pl
|
|
3
|
+
import plotly.express as px
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LineChart(BaseChart):
|
|
7
|
+
def build(
|
|
8
|
+
self,
|
|
9
|
+
chart_name: str,
|
|
10
|
+
df: pl.DataFrame,
|
|
11
|
+
x: str,
|
|
12
|
+
y: str,
|
|
13
|
+
options: dict[str, str] | None = None,
|
|
14
|
+
):
|
|
15
|
+
fig = px.line(df, x=x, y=y, title=chart_name)
|
|
16
|
+
if options is not None:
|
|
17
|
+
self.update_layout(fig, options)
|
|
18
|
+
return fig
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import plotly.express as px
|
|
2
|
+
import polars as pl
|
|
3
|
+
|
|
4
|
+
from .chart import BaseChart
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class PieChart(BaseChart):
|
|
8
|
+
def build(
|
|
9
|
+
self,
|
|
10
|
+
chart_name: str,
|
|
11
|
+
df: pl.DataFrame,
|
|
12
|
+
x: str,
|
|
13
|
+
y: str,
|
|
14
|
+
options: dict[str, str] | None = None,
|
|
15
|
+
):
|
|
16
|
+
fig = px.pie(data_frame=df, values=x, names=y, title=chart_name)
|
|
17
|
+
if options is not None:
|
|
18
|
+
fig = fig.update_layout(options)
|
|
19
|
+
|
|
20
|
+
return fig
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from .pie import PieChart
|
|
2
|
+
from .table import Table
|
|
3
|
+
from .bar import BarChart
|
|
4
|
+
from .line import LineChart
|
|
5
|
+
from .scatter import ScatterChart
|
|
6
|
+
|
|
7
|
+
CHARTS = {
|
|
8
|
+
"line": LineChart(),
|
|
9
|
+
"bar": BarChart(),
|
|
10
|
+
"pie": PieChart(),
|
|
11
|
+
"scatter": ScatterChart(),
|
|
12
|
+
"table": Table(),
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import plotly.express as px
|
|
2
|
+
import polars as pl
|
|
3
|
+
|
|
4
|
+
from .chart import BaseChart
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ScatterChart(BaseChart):
|
|
8
|
+
def build(
|
|
9
|
+
self,
|
|
10
|
+
chart_name: str,
|
|
11
|
+
df: pl.DataFrame,
|
|
12
|
+
x: str,
|
|
13
|
+
y: str,
|
|
14
|
+
options: dict[str, str] | None = None,
|
|
15
|
+
):
|
|
16
|
+
fig = px.scatter(df, x=x, y=y, title=chart_name)
|
|
17
|
+
if options is not None:
|
|
18
|
+
self.update_layout(fig, options)
|
|
19
|
+
return fig
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import polars as pl
|
|
2
|
+
from plotly import graph_objects as go
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Table:
|
|
7
|
+
def build(self, title: str, df: pl.DataFrame, columns: List[str]) -> go.Figure:
|
|
8
|
+
headers = [col for col in df.columns if col in columns]
|
|
9
|
+
data = [col for col in df.select(headers).to_dict(as_series=False).values()]
|
|
10
|
+
table = go.Figure(
|
|
11
|
+
data=go.Table(header=dict(values=headers), cells=dict(values=data))
|
|
12
|
+
)
|
|
13
|
+
return table
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
import plotly.io as pio
|
|
3
|
+
|
|
4
|
+
from .structure.cleaner import clean_builds
|
|
5
|
+
from .datasources import Datasources
|
|
6
|
+
from .dashboard import Dashboard
|
|
7
|
+
from .render import render_dashboard
|
|
8
|
+
from .serve import serve as serve_dashboard
|
|
9
|
+
from .structure.initializer import (
|
|
10
|
+
create_dashboard_template,
|
|
11
|
+
structure_already_present,
|
|
12
|
+
create_structure,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
app = typer.Typer()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@app.command()
|
|
19
|
+
def init() -> None:
|
|
20
|
+
"""
|
|
21
|
+
Initializes dashi folder structure.
|
|
22
|
+
If the structure is already present, it will be skipped.
|
|
23
|
+
After creating the structure, creates the dashboard template, which will be used to generate new dashboards.
|
|
24
|
+
"""
|
|
25
|
+
if not structure_already_present():
|
|
26
|
+
create_structure()
|
|
27
|
+
else:
|
|
28
|
+
print("Structure is already present, skipping creation")
|
|
29
|
+
|
|
30
|
+
create_dashboard_template()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@app.command()
|
|
34
|
+
def build() -> None:
|
|
35
|
+
data_sources = Datasources()
|
|
36
|
+
dashboard = Dashboard(data_sources)
|
|
37
|
+
charts = [
|
|
38
|
+
{"id": f"chart_{i}", "figure": pio.to_json(chart)}
|
|
39
|
+
for i, chart in enumerate(dashboard.charts)
|
|
40
|
+
]
|
|
41
|
+
render_dashboard(dashboard, charts)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@app.command()
|
|
45
|
+
def serve() -> None:
|
|
46
|
+
"""
|
|
47
|
+
Creates a simple server to display the generated dashboards
|
|
48
|
+
"""
|
|
49
|
+
serve_dashboard()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@app.command()
|
|
53
|
+
def clean() -> None:
|
|
54
|
+
"""
|
|
55
|
+
Cleans the dashboard folder from the generated dashboards.
|
|
56
|
+
"""
|
|
57
|
+
clean_builds()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
if __name__ == "__main__":
|
|
61
|
+
app()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .yaml_parser import parse_yaml, NoConfigFile
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Any
|
|
3
|
+
import yaml
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from yaml import CLoader as Loader, CDumper as Dumper
|
|
7
|
+
except ImportError:
|
|
8
|
+
from yaml import Loader, Dumper
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class NoConfigFile(Exception):
|
|
12
|
+
def __init__(self, message: str) -> None:
|
|
13
|
+
self.message = message
|
|
14
|
+
super().__init__()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def parse_yaml(file_path: Path, file_type: str) -> dict:
|
|
18
|
+
"""
|
|
19
|
+
Parses the yaml files in the provided file_path and returns their content as a dict
|
|
20
|
+
Args:
|
|
21
|
+
file_path: a Path object representing the folder to parse
|
|
22
|
+
file_type: the type of file parsed, which is used for the function to
|
|
23
|
+
return the sub-dictionnary with the actual content
|
|
24
|
+
Returns:
|
|
25
|
+
a dictionnary representing the content of the yaml file
|
|
26
|
+
"""
|
|
27
|
+
files: list = list(file_path.glob("*.y*ml"))
|
|
28
|
+
|
|
29
|
+
if not files:
|
|
30
|
+
raise NoConfigFile(f"No YAML config found in {file_path}")
|
|
31
|
+
|
|
32
|
+
file = files[0]
|
|
33
|
+
with open(file, "r") as f:
|
|
34
|
+
config: dict[Any, Any] | None = yaml.load(f, Loader=Loader)
|
|
35
|
+
|
|
36
|
+
if config is None:
|
|
37
|
+
raise ValueError(f"{file} is empty")
|
|
38
|
+
try:
|
|
39
|
+
return config[file_type]
|
|
40
|
+
except KeyError:
|
|
41
|
+
raise ValueError(
|
|
42
|
+
"There is a problem with the datasource file (the format is incorrect)"
|
|
43
|
+
)
|