basic-report 0.1.0__py3-none-any.whl
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.
- basic_report/__init__.py +10 -0
- basic_report/configs/default.yaml +185 -0
- basic_report/css_and_scripts/bootstrap.min.css +7 -0
- basic_report/css_and_scripts/bootstrap.min.js +7 -0
- basic_report/css_and_scripts/dataTables.bootstrap4.min.js +8 -0
- basic_report/css_and_scripts/jquery-3.3.1.slim.min.js +2 -0
- basic_report/css_and_scripts/jquery.dataTables.min.js +166 -0
- basic_report/css_and_scripts/popper.min.js +5 -0
- basic_report/page.py +827 -0
- basic_report/report.py +404 -0
- basic_report/templates/accordion.css +20 -0
- basic_report/templates/accordion.html +20 -0
- basic_report/templates/base.html +59 -0
- basic_report/templates/colors.css +30 -0
- basic_report/templates/columns.html +9 -0
- basic_report/templates/global_links.html +7 -0
- basic_report/templates/header.html +5 -0
- basic_report/templates/image.html +16 -0
- basic_report/templates/list.html +7 -0
- basic_report/templates/navbar.css +17 -0
- basic_report/templates/navbar_left.html +32 -0
- basic_report/templates/navbar_right.html +32 -0
- basic_report/templates/navbar_top.html +25 -0
- basic_report/templates/plot.html +4 -0
- basic_report/templates/report_ball_section.html +80 -0
- basic_report/templates/report_header.html +6 -0
- basic_report/templates/site.css +5 -0
- basic_report/templates/sublevel.html +7 -0
- basic_report/templates/table.css +51 -0
- basic_report/templates/table.html +55 -0
- basic_report/templates/tabs.css +20 -0
- basic_report/templates/tabs.html +29 -0
- basic_report/templates/text.html +3 -0
- basic_report/utils.py +246 -0
- basic_report-0.1.0.dist-info/METADATA +194 -0
- basic_report-0.1.0.dist-info/RECORD +38 -0
- basic_report-0.1.0.dist-info/WHEEL +4 -0
- basic_report-0.1.0.dist-info/licenses/LICENSE.md +21 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<div class="container p-2">
|
|
2
|
+
<ul class="nav nav-pills" role="tablist">
|
|
3
|
+
{% for item in navbar_items -%}
|
|
4
|
+
<li class="nav-item p-1 pill-{{ color }}">
|
|
5
|
+
{% if loop.index == 1 %}
|
|
6
|
+
<a class="nav-link active" data-toggle="pill" href="#{{ item[1] }}" role="tab">{{ item[0] }}</a>
|
|
7
|
+
{% else %}
|
|
8
|
+
<a class="nav-link" data-toggle="pill" href="#{{ item[1] }}" role="tab">{{ item[0] }}</a>
|
|
9
|
+
{% endif %}
|
|
10
|
+
</li>
|
|
11
|
+
{%- endfor %}
|
|
12
|
+
</ul>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div class="container p-2">
|
|
16
|
+
<div class="tab-content">
|
|
17
|
+
{% for item in navbar_items -%}
|
|
18
|
+
{% if loop.index == 1 %}
|
|
19
|
+
<div class="tab-pane fade show active" id="{{ item[1] }}">{{ item[2] }}</div>
|
|
20
|
+
{% else %}
|
|
21
|
+
<div class="tab-pane fade" id="{{ item[1] }}">{{ item[2] }}</div>
|
|
22
|
+
{% endif %}
|
|
23
|
+
{% endfor %}
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<p>
|
|
2
|
+
<div class="container">
|
|
3
|
+
<div class="row justify-content-center">
|
|
4
|
+
<div class="col-3">
|
|
5
|
+
{%- if errors|length > 0 %}
|
|
6
|
+
<button class="btn btn-danger btn-block" type="button" data-toggle="collapse" data-target="#report_ball_errors">
|
|
7
|
+
Errors <span class="badge badge-light"> {{ errors|length }} </span>
|
|
8
|
+
</button>
|
|
9
|
+
{%- else %}
|
|
10
|
+
<button class="btn btn-outline-dark btn-block disabled" type="button">
|
|
11
|
+
No Errors
|
|
12
|
+
</button>
|
|
13
|
+
{%- endif %}
|
|
14
|
+
</div>
|
|
15
|
+
<div class="col-3">
|
|
16
|
+
{%- if warnings|length > 0 %}
|
|
17
|
+
<button class="btn btn-warning btn-block" type="button" data-toggle="collapse" data-target="#report_ball_warnings">
|
|
18
|
+
Warnings <span class="badge badge-light"> {{ warnings|length }} </span>
|
|
19
|
+
</button>
|
|
20
|
+
{%- else %}
|
|
21
|
+
<button class="btn btn-outline-dark btn-block disabled" type="button">
|
|
22
|
+
No Warnings
|
|
23
|
+
</button>
|
|
24
|
+
{%- endif %}
|
|
25
|
+
</div>
|
|
26
|
+
<div class="col-3">
|
|
27
|
+
{%- if info|length > 0 %}
|
|
28
|
+
<button class="btn btn-success btn-block" type="button" data-toggle="collapse" data-target="#report_ball_info">
|
|
29
|
+
Info <span class="badge badge-light"> {{ info|length }} </span>
|
|
30
|
+
</button>
|
|
31
|
+
{%- else %}
|
|
32
|
+
<button class="btn btn-outline-dark btn-block disabled" type="button">
|
|
33
|
+
No Info
|
|
34
|
+
</button>
|
|
35
|
+
{%- endif %}
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
<p>
|
|
42
|
+
<div class="container p-1">
|
|
43
|
+
{%- if errors|length > 0 %}
|
|
44
|
+
<div class="collapse" id="report_ball_errors">
|
|
45
|
+
<div class="alert alert-danger text-center" role="alert">Errors</div>
|
|
46
|
+
<div class="container">
|
|
47
|
+
<ol>
|
|
48
|
+
{% for item in errors -%}
|
|
49
|
+
<li class="text-{{ color }}">{{ item }}</li>
|
|
50
|
+
{%- endfor %}
|
|
51
|
+
</ol>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
{%- endif -%}
|
|
55
|
+
{%- if warnings|length > 0 %}
|
|
56
|
+
<div class="collapse" id="report_ball_warnings">
|
|
57
|
+
<div class="alert alert-warning text-center" role="alert">Warnings</div>
|
|
58
|
+
<div class="container">
|
|
59
|
+
<ol>
|
|
60
|
+
{% for item in warnings -%}
|
|
61
|
+
<li class="text-{{ color }}">{{ item }}</li>
|
|
62
|
+
{%- endfor %}
|
|
63
|
+
</ol>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
{%- endif -%}
|
|
67
|
+
{%- if info|length > 0 %}
|
|
68
|
+
<div class="collapse" id="report_ball_info">
|
|
69
|
+
<div class="alert alert-success text-center" role="alert">Info</div>
|
|
70
|
+
<div class="container">
|
|
71
|
+
<ol>
|
|
72
|
+
{% for item in info -%}
|
|
73
|
+
<li class="text-{{ color }}">{{ item }}</li>
|
|
74
|
+
{%- endfor %}
|
|
75
|
+
</ol>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
{%- endif -%}
|
|
79
|
+
</div>
|
|
80
|
+
</p>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
|
|
2
|
+
/* Search input + length dropdown */
|
|
3
|
+
.dataTables_wrapper .form-control {
|
|
4
|
+
background-color: {{ table_controls_background_color }};
|
|
5
|
+
border: 1px solid {{ table_controls_border_color }};
|
|
6
|
+
color: {{ table_controls_font_color }};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* Focus state */
|
|
10
|
+
.dataTables_wrapper .form-control:focus {
|
|
11
|
+
background-color: {{ table_controls_background_color }};
|
|
12
|
+
border-color: {{ table_controls_border_color }};
|
|
13
|
+
color: {{ table_controls_font_color }};
|
|
14
|
+
box-shadow: none;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.dataTables_wrapper {
|
|
18
|
+
color: {{ table_controls_font_color }};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.dataTables_wrapper .dataTables_info,
|
|
22
|
+
.dataTables_wrapper .dataTables_length label,
|
|
23
|
+
.dataTables_wrapper .dataTables_filter label {
|
|
24
|
+
color: {{ table_controls_font_color }};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Pagination container */
|
|
28
|
+
.dataTables_wrapper .pagination .page-link {
|
|
29
|
+
background-color: {{ table_controls_background_color }};
|
|
30
|
+
border: 1px solid {{ table_controls_border_color }};
|
|
31
|
+
color: {{ table_controls_font_color }};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Hover */
|
|
35
|
+
.dataTables_wrapper .pagination .page-link:hover {
|
|
36
|
+
background-color: {{ table_controls_background_color }};
|
|
37
|
+
border-color: {{ table_pagination_hover_border_color }};
|
|
38
|
+
color: {{ table_pagination_hover_font_color }};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Active page */
|
|
42
|
+
.dataTables_wrapper .pagination .page-item.active .page-link {
|
|
43
|
+
background-color: {{ table_pagination_active_background_color }};
|
|
44
|
+
border-color: {{ table_pagination_active_border_color }};
|
|
45
|
+
color: {{ table_pagination_active_font_color }};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.dataTables_wrapper .pagination .page-link:focus {
|
|
49
|
+
outline: none;
|
|
50
|
+
box-shadow: none;
|
|
51
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
var {{ table_id }}DataSet = {{ table_data }};
|
|
3
|
+
|
|
4
|
+
$(document).ready(function() {
|
|
5
|
+
$('#{{ table_id }}').DataTable( {
|
|
6
|
+
data: {{ table_id }}DataSet,
|
|
7
|
+
columns: [
|
|
8
|
+
{% for c in table_columns -%}
|
|
9
|
+
{ title: "{{ c }}" },
|
|
10
|
+
{% endfor %} ],
|
|
11
|
+
{% if not 'page' in options -%}
|
|
12
|
+
"paging": false,
|
|
13
|
+
{%- endif %}
|
|
14
|
+
{% if not 'info' in options -%}
|
|
15
|
+
"info": false,
|
|
16
|
+
{%- endif %}
|
|
17
|
+
{% if not 'search' in options -%}
|
|
18
|
+
"searching": false,
|
|
19
|
+
{%- endif %}
|
|
20
|
+
{% if order is not none -%}
|
|
21
|
+
"order": {{ order }},
|
|
22
|
+
{%- endif %}
|
|
23
|
+
{% if 'no_sort' in options -%}
|
|
24
|
+
"ordering": false,
|
|
25
|
+
{%- endif -%}
|
|
26
|
+
"autoWidth": false,
|
|
27
|
+
} );
|
|
28
|
+
} );
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
{% if 'full_width' in options %}
|
|
32
|
+
<div class="container-fluid p-2">
|
|
33
|
+
{% else %}
|
|
34
|
+
<div class="container p-2">
|
|
35
|
+
{% endif %}
|
|
36
|
+
<table id="{{ table_id }}" class="table text-{{ align }} text-{{ color }} table-striped table-sm">
|
|
37
|
+
{% if footers|length %}
|
|
38
|
+
<tfoot class="double-top-border">
|
|
39
|
+
{% for foot in footers %}
|
|
40
|
+
<tr>
|
|
41
|
+
{% for item in foot %}
|
|
42
|
+
<td>{{ item }}</td>
|
|
43
|
+
{% endfor %}
|
|
44
|
+
</tr>
|
|
45
|
+
{% endfor %}
|
|
46
|
+
</tfoot>
|
|
47
|
+
{% endif %}
|
|
48
|
+
{% if caption != "" %}
|
|
49
|
+
<caption>
|
|
50
|
+
{{ caption }}
|
|
51
|
+
</caption>
|
|
52
|
+
{% endif %}
|
|
53
|
+
</table>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.nav-tabs {
|
|
2
|
+
border-bottom: {{ tab_border_bottom_size }} solid {{ tab_border_bottom_color }};
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.nav-tabs .nav-link {
|
|
6
|
+
color: {{ tab_inactive_font_color }};
|
|
7
|
+
font-weight: {{ tab_inactive_font_weight }};
|
|
8
|
+
border: none;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.nav-tabs .nav-link:hover {
|
|
12
|
+
color: {{ tab_hover_font_color }};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.nav-tabs .nav-link.active {
|
|
16
|
+
color: {{ tab_active_font_color }};
|
|
17
|
+
background: {{ tab_active_background_color }};
|
|
18
|
+
font-weight: {{ tab_active_font_weight }};
|
|
19
|
+
border-bottom: {{ tab_active_border_bottom_size }} solid {{ tab_active_border_bottom_color }};
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<div class="container p-2">
|
|
2
|
+
<ul class="nav nav-tabs">
|
|
3
|
+
{% for item in tabbed_items %}
|
|
4
|
+
<li class="nav-item">
|
|
5
|
+
{% if loop.index == 1 %}
|
|
6
|
+
<a class="nav-link active" data-toggle="tab" href="#{{ item[1] }}">
|
|
7
|
+
{% else %}
|
|
8
|
+
<a class="nav-link" data-toggle="tab" href="#{{ item[1] }}">
|
|
9
|
+
{% endif %}
|
|
10
|
+
{{ item[0] }}
|
|
11
|
+
</a>
|
|
12
|
+
</li>
|
|
13
|
+
{% endfor %}
|
|
14
|
+
</ul>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<div class="container p-1">
|
|
18
|
+
<div class="tab-content justify-content-center">
|
|
19
|
+
{% for item in tabbed_items %}
|
|
20
|
+
{% if loop.index == 1 %}
|
|
21
|
+
<div class="tab-pane container active " id="{{ item[1] }}">
|
|
22
|
+
{% else %}
|
|
23
|
+
<div class="tab-pane container fade " id="{{ item[1] }}">
|
|
24
|
+
{% endif %}
|
|
25
|
+
{{ item[2] }}
|
|
26
|
+
</div>
|
|
27
|
+
{% endfor %}
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
basic_report/utils.py
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
from jinja2 import Environment, FileSystemLoader
|
|
3
|
+
from loguru import logger
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any, Union, Optional
|
|
6
|
+
|
|
7
|
+
from . import TEMPLATE_DIR
|
|
8
|
+
|
|
9
|
+
#----------------------------------------------------------------------------------------------------------------------#
|
|
10
|
+
# region COLOR MAP
|
|
11
|
+
#----------------------------------------------------------------------------------------------------------------------#
|
|
12
|
+
class ColorMap:
|
|
13
|
+
""" Color map object for handling the color space of the report """
|
|
14
|
+
def __init__(self, config: dict[str, Any], color_mode: str, text_color: Optional[str]=None):
|
|
15
|
+
""" Initialize a new color map given a config dict
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
config (dict[str, Any]): The configuration for this report. Mainly responsible for defining new color
|
|
19
|
+
profiles that can later be used
|
|
20
|
+
color_mode (str): Select the current color mode of the report, i.e., `dark` or `light`
|
|
21
|
+
text_color (Optional[str]): Override for the text color of the report. For a more granular approach use the
|
|
22
|
+
config file
|
|
23
|
+
"""
|
|
24
|
+
self.config = config
|
|
25
|
+
self.color_mode = color_mode
|
|
26
|
+
self.text_color = text_color
|
|
27
|
+
|
|
28
|
+
# Prepare the jinja templater
|
|
29
|
+
self.file_loader = FileSystemLoader(TEMPLATE_DIR)
|
|
30
|
+
self.jinja_env = Environment(loader=self.file_loader)
|
|
31
|
+
|
|
32
|
+
# Default color map - Maps the default bootstrap colors to their respective color names
|
|
33
|
+
self.cm = {
|
|
34
|
+
'blue': 'primary',
|
|
35
|
+
'gray': 'secondary',
|
|
36
|
+
'green': 'success',
|
|
37
|
+
'red': 'danger',
|
|
38
|
+
'yellow': 'warning',
|
|
39
|
+
'teal': 'info',
|
|
40
|
+
'black': 'dark',
|
|
41
|
+
'primary': 'primary',
|
|
42
|
+
'secondary': 'secondary',
|
|
43
|
+
'success': 'success',
|
|
44
|
+
'danger': 'danger',
|
|
45
|
+
'warning': 'warning',
|
|
46
|
+
'info': 'info',
|
|
47
|
+
'dark': 'dark',
|
|
48
|
+
'light': 'light',
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Create the custom color CSS that will be injected and make the profiles available in the color map
|
|
52
|
+
for cc in self.config['custom_colors']:
|
|
53
|
+
self.cm[cc] = cc
|
|
54
|
+
|
|
55
|
+
#---------------#
|
|
56
|
+
# Magic Methods #
|
|
57
|
+
#---------------#
|
|
58
|
+
def __getitem__(self, key: str) -> str:
|
|
59
|
+
""" Verify the color name and return the proper color mapping """
|
|
60
|
+
return self.verify_and_get_color(key)
|
|
61
|
+
|
|
62
|
+
#---------#
|
|
63
|
+
# Private #
|
|
64
|
+
#---------#
|
|
65
|
+
def _make_color_css_files(self, output_dir: Path):
|
|
66
|
+
""" Create the custom color css file """
|
|
67
|
+
# Create CSS string
|
|
68
|
+
color_items = [v | {'name': k} for k,v in self.config['custom_colors'].items()]
|
|
69
|
+
|
|
70
|
+
# Color CSS
|
|
71
|
+
template = self.jinja_env.get_template('colors.css')
|
|
72
|
+
css = template.render(color_items=color_items)
|
|
73
|
+
|
|
74
|
+
# Dump to scripts dir
|
|
75
|
+
custom_color_file = output_dir / 'custom_colors.css'
|
|
76
|
+
custom_color_file.write_text(css)
|
|
77
|
+
|
|
78
|
+
# Color CSS
|
|
79
|
+
template = self.jinja_env.get_template('navbar.css')
|
|
80
|
+
css = template.render(color_items=color_items)
|
|
81
|
+
|
|
82
|
+
# Dump to scripts dir
|
|
83
|
+
navbar_file = output_dir / 'navbar.css'
|
|
84
|
+
navbar_file.write_text(css)
|
|
85
|
+
|
|
86
|
+
def _make_css_file(self, element_type: str, output_dir: Path):
|
|
87
|
+
""" Create the custom css files for the element type """
|
|
88
|
+
# Create CSS string
|
|
89
|
+
colors = self.config['css'][element_type][self.color_mode]
|
|
90
|
+
template = self.jinja_env.get_template(f'{element_type}.css')
|
|
91
|
+
css = template.render(**colors)
|
|
92
|
+
|
|
93
|
+
# Dump to scripts dir
|
|
94
|
+
css_file = output_dir / f'{element_type}.css'
|
|
95
|
+
css_file.write_text(css)
|
|
96
|
+
|
|
97
|
+
#-----#
|
|
98
|
+
# API #
|
|
99
|
+
#-----#
|
|
100
|
+
def verify_and_get_color(self, color: str) -> str:
|
|
101
|
+
""" Check that the requested color is actually available
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
color (str): Color to check
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
str - color name to use
|
|
108
|
+
"""
|
|
109
|
+
if color not in self.cm:
|
|
110
|
+
msg = f'No color `{color}` found. Available: {self.cm.keys()}'
|
|
111
|
+
logger.error(msg)
|
|
112
|
+
raise RuntimeError(msg)
|
|
113
|
+
|
|
114
|
+
return self.cm[color]
|
|
115
|
+
|
|
116
|
+
def get_default_color(self, field: str) -> str:
|
|
117
|
+
""" Determine the correct default color for a given color mode and field
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
field (str): The type/field the color should be used for
|
|
121
|
+
color_mode (str): The color mode of the report, i.e., either `light` or `dark`
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
str - The color to be used
|
|
125
|
+
"""
|
|
126
|
+
if self.text_color is None or field not in ['text', 'table', 'report_ball']:
|
|
127
|
+
color = self.config['default_color_profiles'][self.color_mode].get(field)
|
|
128
|
+
else:
|
|
129
|
+
color = self.text_color
|
|
130
|
+
|
|
131
|
+
if color is None:
|
|
132
|
+
msg = f'No default color defined for `{field}` with color mode `{self.color_mode}`'
|
|
133
|
+
logger.error(msg)
|
|
134
|
+
raise RuntimeError(msg)
|
|
135
|
+
return color
|
|
136
|
+
|
|
137
|
+
def make_css_files(self, output_dir: Path):
|
|
138
|
+
""" Create the custom css files for the site
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
output_dir (Path): The reports css and script dir
|
|
142
|
+
"""
|
|
143
|
+
self._make_color_css_files(output_dir)
|
|
144
|
+
for element_type in ['site', 'tabs', 'accordion', 'table']:
|
|
145
|
+
self._make_css_file(element_type, output_dir)
|
|
146
|
+
|
|
147
|
+
#----------------------------------------------------------------------------------------------------------------------#
|
|
148
|
+
# region MISC HELPER
|
|
149
|
+
#----------------------------------------------------------------------------------------------------------------------#
|
|
150
|
+
def coerce_to_date(date: Union[str, int, datetime.date, datetime.datetime]) -> datetime.date:
|
|
151
|
+
""" Coerce random data formats to a datetime.date object
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
date (Union[str, int, datetime.date, datetime.datetime]): The date to coerce
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
datetime.date - The coerce date object
|
|
158
|
+
"""
|
|
159
|
+
if isinstance(date, datetime.date):
|
|
160
|
+
return date
|
|
161
|
+
elif isinstance(date, datetime.datetime):
|
|
162
|
+
return date.date
|
|
163
|
+
elif isinstance(date, int):
|
|
164
|
+
date = str(int)
|
|
165
|
+
|
|
166
|
+
if not isinstance(date, str):
|
|
167
|
+
msg = f'Cannot coerce date {date}'
|
|
168
|
+
logger.error(msg)
|
|
169
|
+
raise RuntimeError(msg)
|
|
170
|
+
|
|
171
|
+
if len(date) == 6: # noqa: PLR2004
|
|
172
|
+
year = int(date[:2])
|
|
173
|
+
if year < 50: # noqa: PLR2004
|
|
174
|
+
year += 2000
|
|
175
|
+
else:
|
|
176
|
+
year += 1900
|
|
177
|
+
month = int(date[2:4])
|
|
178
|
+
day = int(date[4:])
|
|
179
|
+
|
|
180
|
+
elif len(date) == 8: # noqa: PLR2004
|
|
181
|
+
if date.isdigit():
|
|
182
|
+
year = int(date[:4])
|
|
183
|
+
month = int(date[4:6])
|
|
184
|
+
day = int(date[6:])
|
|
185
|
+
else:
|
|
186
|
+
year = int(date[:2])
|
|
187
|
+
if year < 50: # noqa: PLR2004
|
|
188
|
+
year += 2000
|
|
189
|
+
else:
|
|
190
|
+
year += 1900
|
|
191
|
+
month = int(date[3:5])
|
|
192
|
+
day = int(date[6:])
|
|
193
|
+
|
|
194
|
+
elif len(date) == 10: # noqa: PLR2004
|
|
195
|
+
year = int(date[:4])
|
|
196
|
+
month = int(date[5:7])
|
|
197
|
+
day = int(date[8:])
|
|
198
|
+
return datetime.date(year, month, day)
|
|
199
|
+
|
|
200
|
+
def verify_alignment(align: str) -> str:
|
|
201
|
+
""" Check that the requested alignment is actually available
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
align (str): The alignment tag that needs to be verified
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
str - The alignment if it is acceptable
|
|
208
|
+
"""
|
|
209
|
+
alignments = ['left', 'center', 'right']
|
|
210
|
+
if align not in alignments:
|
|
211
|
+
msg = f'Unknown alignment {align}. Available: {alignments}'
|
|
212
|
+
logger.error(msg)
|
|
213
|
+
raise RuntimeError(msg)
|
|
214
|
+
return align
|
|
215
|
+
|
|
216
|
+
def verify_color_mode(color_mode: str) -> str:
|
|
217
|
+
""" Check that the requested alignment is actually available
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
color_mode (str): The alignment tag that needs to be verified
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
str - The alignment if it is acceptable
|
|
224
|
+
"""
|
|
225
|
+
color_modes = ['light', 'dark']
|
|
226
|
+
if color_mode not in color_modes:
|
|
227
|
+
msg = f'Unknown color_mode {color_mode}. Available: {color_modes}'
|
|
228
|
+
logger.error(msg)
|
|
229
|
+
raise RuntimeError(msg)
|
|
230
|
+
return color_mode
|
|
231
|
+
|
|
232
|
+
def default(var: Any, default: Any) -> Any:
|
|
233
|
+
""" Helper function to check kwargs and set them to a default
|
|
234
|
+
|
|
235
|
+
You could simply use var or default. But for future additions we will use a separat function here
|
|
236
|
+
Args:
|
|
237
|
+
var (Any): The input variable
|
|
238
|
+
default (Any): Default value for the variable
|
|
239
|
+
|
|
240
|
+
Returns
|
|
241
|
+
Any - Either the variable itself, or the default value if var is `None`
|
|
242
|
+
"""
|
|
243
|
+
if var is None:
|
|
244
|
+
return default
|
|
245
|
+
else:
|
|
246
|
+
return var
|