mayutils 1.2.0__tar.gz → 1.2.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.
- {mayutils-1.2.0 → mayutils-1.2.2}/PKG-INFO +3 -1
- {mayutils-1.2.0 → mayutils-1.2.2}/pyproject.toml +7 -1
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/__init__.py +1 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/data/live.py +26 -2
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/environment/benchmarking.py +1 -1
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/environment/logging.py +6 -6
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/interfaces/google.py +20 -13
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/interfaces/microsoft.py +30 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/colours.py +6 -1
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/dataframes.py +10 -7
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/datetime.py +7 -5
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/decorators.py +1 -1
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/functions.py +4 -1
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/scripts/versioning.py +1 -1
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/graphs/plotly/charts.py +89 -31
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/graphs/plotly/traces.py +1 -3
- mayutils-1.2.0/src/mayutils/.DS_Store +0 -0
- mayutils-1.2.0/src/mayutils/data/.DS_Store +0 -0
- mayutils-1.2.0/src/mayutils/data/queries/.DS_Store +0 -0
- mayutils-1.2.0/src/mayutils/scripts/.DS_Store +0 -0
- mayutils-1.2.0/src/mayutils/visualisation/.DS_Store +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/LICENSE +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/README.md +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/core/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/core/constants.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/data/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/data/analysis/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/data/cache/.gitkeep +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/data/local.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/data/queries/.gitkeep +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/data/queries/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/data/queries/examples/.gitkeep +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/data/read.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/environment/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/environment/databases.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/environment/filesystem.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/environment/memoisation.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/environment/oauth.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/environment/webdrivers.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/export/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/export/images.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/export/pdf.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/export/slides.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/interfaces/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/interfaces/streamlit.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/mathematics/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/mathematics/numba.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/mathematics/numpy.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/classes.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/dictionaries.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/hashing.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/numbers.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/strings.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/objects/types.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/scripts/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/scripts/clear_cache.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/testing/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/console.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/graphs/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/graphs/combine.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/graphs/matplotlib/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/graphs/matplotlib/template.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/graphs/plotly/__init__.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/graphs/plotly/templates.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/graphs/plotly/utilities.py +0 -0
- {mayutils-1.2.0 → mayutils-1.2.2}/src/mayutils/visualisation/notebook.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: mayutils
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: Utilities for Python from Mayuran Visakan
|
|
5
5
|
Author: Mayuran Visakan
|
|
6
6
|
Author-email: Mayuran Visakan <mayuran.k.v@gmail.com>
|
|
@@ -48,6 +48,7 @@ Requires-Dist: numba>=0.62.0rc1
|
|
|
48
48
|
Requires-Dist: numpy>=2.3.2
|
|
49
49
|
Requires-Dist: numpy-financial>=1.0.0
|
|
50
50
|
Requires-Dist: pandas>=2.3.2
|
|
51
|
+
Requires-Dist: pandas-stubs>=2.3.2.250827
|
|
51
52
|
Requires-Dist: pathlib>=1.0.1
|
|
52
53
|
Requires-Dist: pendulum[test]>=3.1.0
|
|
53
54
|
Requires-Dist: pillow>=11.3.0
|
|
@@ -71,6 +72,7 @@ Requires-Dist: snowflake-sqlalchemy>=1.7.6
|
|
|
71
72
|
Requires-Dist: sqlalchemy>=2.0.43
|
|
72
73
|
Requires-Dist: streamlit>=1.49.0
|
|
73
74
|
Requires-Dist: typer>=0.16.1
|
|
75
|
+
Requires-Dist: types-six>=1.17.0.20250515
|
|
74
76
|
Requires-Dist: unicodeit>=0.7.5
|
|
75
77
|
Requires-Dist: ruff>=0.9.6 ; extra == 'dev'
|
|
76
78
|
Requires-Dist: mypy>=1.15.0 ; extra == 'dev'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mayutils"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.2"
|
|
4
4
|
description = "Utilities for Python from Mayuran Visakan"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Mayuran Visakan", email = "mayuran.k.v@gmail.com" }
|
|
@@ -32,6 +32,7 @@ dependencies = [
|
|
|
32
32
|
"numpy>=2.3.2",
|
|
33
33
|
"numpy-financial>=1.0.0",
|
|
34
34
|
"pandas>=2.3.2",
|
|
35
|
+
"pandas-stubs>=2.3.2.250827",
|
|
35
36
|
"pathlib>=1.0.1",
|
|
36
37
|
"pendulum[test]>=3.1.0",
|
|
37
38
|
"pillow>=11.3.0",
|
|
@@ -55,6 +56,7 @@ dependencies = [
|
|
|
55
56
|
"sqlalchemy>=2.0.43",
|
|
56
57
|
"streamlit>=1.49.0",
|
|
57
58
|
"typer>=0.16.1",
|
|
59
|
+
"types-six>=1.17.0.20250515",
|
|
58
60
|
"unicodeit>=0.7.5",
|
|
59
61
|
]
|
|
60
62
|
|
|
@@ -73,6 +75,10 @@ generate_encryption_key = "mayutils.environment.oauth:generate_fernet_key"
|
|
|
73
75
|
[tool.uv]
|
|
74
76
|
prerelease = "if-necessary-or-explicit"
|
|
75
77
|
|
|
78
|
+
[tool.pyright]
|
|
79
|
+
venvPath = "."
|
|
80
|
+
venv = ".venv"
|
|
81
|
+
|
|
76
82
|
[build-system]
|
|
77
83
|
requires = ["uv_build>=0.8.14,<0.9.0"]
|
|
78
84
|
build-backend = "uv_build"
|
|
@@ -18,7 +18,7 @@ class LiveData(object):
|
|
|
18
18
|
- Data is stored in a pandas DataFrame
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
-
def
|
|
21
|
+
def _initialise(
|
|
22
22
|
self,
|
|
23
23
|
query_string: str,
|
|
24
24
|
engine: EngineWrapper,
|
|
@@ -61,6 +61,30 @@ class LiveData(object):
|
|
|
61
61
|
|
|
62
62
|
return None
|
|
63
63
|
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
query_string: str,
|
|
67
|
+
engine: EngineWrapper,
|
|
68
|
+
index_column: str,
|
|
69
|
+
start_timestamp: datetime,
|
|
70
|
+
rolling: bool = True,
|
|
71
|
+
aggregations: dict[str, Callable[[DataFrame], DataFrame]] = {},
|
|
72
|
+
update_frequency: Optional[timedelta] = None,
|
|
73
|
+
time_format: str = "%Y-%m-%d",
|
|
74
|
+
**format_kwargs,
|
|
75
|
+
) -> None:
|
|
76
|
+
return self._initialise(
|
|
77
|
+
query_string=query_string,
|
|
78
|
+
engine=engine,
|
|
79
|
+
index_column=index_column,
|
|
80
|
+
start_timestamp=start_timestamp,
|
|
81
|
+
rolling=rolling,
|
|
82
|
+
aggregations=aggregations,
|
|
83
|
+
update_frequency=update_frequency,
|
|
84
|
+
time_format=time_format,
|
|
85
|
+
**format_kwargs,
|
|
86
|
+
)
|
|
87
|
+
|
|
64
88
|
def update(
|
|
65
89
|
self,
|
|
66
90
|
engine: Optional[EngineWrapper] = None,
|
|
@@ -118,7 +142,7 @@ class LiveData(object):
|
|
|
118
142
|
self,
|
|
119
143
|
start_timestamp: Optional[datetime] = None,
|
|
120
144
|
) -> Self:
|
|
121
|
-
self.
|
|
145
|
+
self._initialise(
|
|
122
146
|
query_string=self.query_string,
|
|
123
147
|
engine=self.engine,
|
|
124
148
|
index_column=self.index_column,
|
|
@@ -117,7 +117,7 @@ class Logger(logging.Logger):
|
|
|
117
117
|
|
|
118
118
|
return cls.clone(logger=logger)
|
|
119
119
|
|
|
120
|
-
def
|
|
120
|
+
def report(
|
|
121
121
|
self,
|
|
122
122
|
*msgs: str,
|
|
123
123
|
sep: str = " ",
|
|
@@ -176,7 +176,7 @@ def _log(
|
|
|
176
176
|
*args,
|
|
177
177
|
**kwargs,
|
|
178
178
|
) -> Any:
|
|
179
|
-
logger.
|
|
179
|
+
logger.report(
|
|
180
180
|
f"Calling function: {func.__name__}",
|
|
181
181
|
level=level,
|
|
182
182
|
show=show,
|
|
@@ -189,7 +189,7 @@ def _log(
|
|
|
189
189
|
**kwargs,
|
|
190
190
|
)
|
|
191
191
|
end = time.perf_counter()
|
|
192
|
-
logger.
|
|
192
|
+
logger.report(
|
|
193
193
|
f"Function {func.__name__} returned ({end - start:.2f}s): {result}",
|
|
194
194
|
level=level,
|
|
195
195
|
show=show,
|
|
@@ -198,7 +198,7 @@ def _log(
|
|
|
198
198
|
return result
|
|
199
199
|
except Exception as exception:
|
|
200
200
|
end = time.perf_counter()
|
|
201
|
-
logger.
|
|
201
|
+
logger.report(
|
|
202
202
|
f"Function {func.__name__} raised an exception ({end - start:.2f}s): {exception}",
|
|
203
203
|
level=logging.ERROR,
|
|
204
204
|
exc_info=True,
|
|
@@ -243,13 +243,13 @@ def log(
|
|
|
243
243
|
raise ValueError("No target provided")
|
|
244
244
|
if isinstance(target, type):
|
|
245
245
|
return _log_class(
|
|
246
|
-
|
|
246
|
+
target,
|
|
247
247
|
*args,
|
|
248
248
|
**kwargs,
|
|
249
249
|
)
|
|
250
250
|
else:
|
|
251
251
|
return _log(
|
|
252
|
-
|
|
252
|
+
target,
|
|
253
253
|
*args,
|
|
254
254
|
**kwargs,
|
|
255
255
|
)
|
|
@@ -677,6 +677,11 @@ class Slides(object):
|
|
|
677
677
|
if y_shift is None:
|
|
678
678
|
y_shift = self.height * 0.05
|
|
679
679
|
|
|
680
|
+
theme_color = ""
|
|
681
|
+
parsed_colour = Colour(0, 0, 0)
|
|
682
|
+
theme_background_color = ""
|
|
683
|
+
parsed_background_colour = Colour(0, 0, 0)
|
|
684
|
+
|
|
680
685
|
if colour is not None and not isinstance(colour, Colour):
|
|
681
686
|
if colour.startswith("theme-"):
|
|
682
687
|
theme_color = colour[len("theme-") :]
|
|
@@ -695,7 +700,7 @@ class Slides(object):
|
|
|
695
700
|
f"Slide number {slide_number} is out of range. Presentation has {len(self.slides)} slides."
|
|
696
701
|
)
|
|
697
702
|
|
|
698
|
-
requests = [
|
|
703
|
+
requests: list[dict[str, Any]] = [
|
|
699
704
|
{
|
|
700
705
|
"createShape": {
|
|
701
706
|
"objectId": element_id,
|
|
@@ -747,20 +752,22 @@ class Slides(object):
|
|
|
747
752
|
"foregroundColor": (
|
|
748
753
|
{}
|
|
749
754
|
if colour is None
|
|
750
|
-
else
|
|
751
|
-
|
|
752
|
-
"
|
|
753
|
-
"
|
|
754
|
-
|
|
755
|
-
|
|
755
|
+
else (
|
|
756
|
+
{
|
|
757
|
+
"opaqueColor": {
|
|
758
|
+
"rgbColor": {
|
|
759
|
+
"red": parsed_colour.r / 255,
|
|
760
|
+
"green": parsed_colour.g / 255,
|
|
761
|
+
"blue": parsed_colour.b / 255,
|
|
762
|
+
}
|
|
756
763
|
}
|
|
757
764
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
765
|
+
if not (
|
|
766
|
+
isinstance(colour, str)
|
|
767
|
+
and colour.startswith("theme-")
|
|
768
|
+
)
|
|
769
|
+
else {"themeColor": theme_color}
|
|
762
770
|
)
|
|
763
|
-
else {"themeColor": theme_color}
|
|
764
771
|
)
|
|
765
772
|
}
|
|
766
773
|
if colour
|
|
@@ -1510,7 +1517,7 @@ class Sheets(object):
|
|
|
1510
1517
|
]:
|
|
1511
1518
|
raise ValueError(f"Sheet title {new_title} is already used")
|
|
1512
1519
|
|
|
1513
|
-
sheet_properties = {}
|
|
1520
|
+
sheet_properties: dict[str, str | int] = {}
|
|
1514
1521
|
if to_position is not None:
|
|
1515
1522
|
sheet_properties["index"] = target_index
|
|
1516
1523
|
|
|
@@ -49,6 +49,12 @@ class Presentation:
|
|
|
49
49
|
len(self.internal.slide_layouts) - 1
|
|
50
50
|
]
|
|
51
51
|
|
|
52
|
+
# TODO: Implement display/__repr__/_repr_mimebundle_
|
|
53
|
+
# def __repr__(
|
|
54
|
+
# self,
|
|
55
|
+
# text: str,
|
|
56
|
+
# ) -> Self:
|
|
57
|
+
|
|
52
58
|
@property
|
|
53
59
|
def layouts(
|
|
54
60
|
self,
|
|
@@ -89,6 +95,12 @@ class Presentation:
|
|
|
89
95
|
) -> None:
|
|
90
96
|
self.internal.slide_width = value
|
|
91
97
|
|
|
98
|
+
# TODO: Implement
|
|
99
|
+
# @property
|
|
100
|
+
# def title(
|
|
101
|
+
# self,
|
|
102
|
+
# ) -> str:
|
|
103
|
+
|
|
92
104
|
@property
|
|
93
105
|
def slides(
|
|
94
106
|
self,
|
|
@@ -306,6 +318,24 @@ class Presentation:
|
|
|
306
318
|
|
|
307
319
|
return self
|
|
308
320
|
|
|
321
|
+
# TODO: Implement
|
|
322
|
+
# def insert_markdown(
|
|
323
|
+
# self,
|
|
324
|
+
# text: str,
|
|
325
|
+
# ) -> Self:
|
|
326
|
+
|
|
327
|
+
# TODO: Implement
|
|
328
|
+
# def insert_image(
|
|
329
|
+
# self,
|
|
330
|
+
# image_path: Path | str,
|
|
331
|
+
# ) -> Self:
|
|
332
|
+
|
|
333
|
+
# TODO: Implement
|
|
334
|
+
# def insert_table(
|
|
335
|
+
# self,
|
|
336
|
+
# table: DataFrame | Styler,
|
|
337
|
+
# ) -> Self:
|
|
338
|
+
|
|
309
339
|
def save(
|
|
310
340
|
self,
|
|
311
341
|
file_path: Path | str,
|
|
@@ -138,7 +138,12 @@ class Colour:
|
|
|
138
138
|
rgb = getrgb(colour)
|
|
139
139
|
opacity = rgb[3] if len(rgb) == 4 else opacity
|
|
140
140
|
|
|
141
|
-
return cls(
|
|
141
|
+
return cls(
|
|
142
|
+
r=rgb[0],
|
|
143
|
+
g=rgb[1],
|
|
144
|
+
b=rgb[2],
|
|
145
|
+
a=opacity,
|
|
146
|
+
)
|
|
142
147
|
|
|
143
148
|
def set_opacity(
|
|
144
149
|
self,
|
|
@@ -243,7 +243,6 @@ class DataframeUtilsAccessor(object):
|
|
|
243
243
|
def save(
|
|
244
244
|
self,
|
|
245
245
|
path: Path | str,
|
|
246
|
-
*args,
|
|
247
246
|
**kwargs,
|
|
248
247
|
) -> Path:
|
|
249
248
|
path = Path(path)
|
|
@@ -251,22 +250,25 @@ class DataframeUtilsAccessor(object):
|
|
|
251
250
|
if path.suffix in [".png", ".jpeg", ".jpg", ".pdf", ".svg", ".eps"]:
|
|
252
251
|
return self.styler.save(
|
|
253
252
|
path=path,
|
|
254
|
-
*args,
|
|
255
253
|
**kwargs,
|
|
256
254
|
)
|
|
255
|
+
|
|
257
256
|
elif path.suffix == ".parquet":
|
|
258
257
|
self.df.to_parquet(
|
|
259
258
|
path=path,
|
|
260
259
|
index=True,
|
|
261
260
|
)
|
|
261
|
+
|
|
262
262
|
elif path.suffix == ".feather":
|
|
263
263
|
raise NotImplementedError("Feather not implemented")
|
|
264
264
|
self.df.to_feather(path)
|
|
265
|
+
|
|
265
266
|
elif path.suffix == ".csv":
|
|
266
267
|
self.df.to_csv(
|
|
267
268
|
path_or_buf=path,
|
|
268
269
|
index=True,
|
|
269
270
|
)
|
|
271
|
+
|
|
270
272
|
elif path.suffix == ".xlsx":
|
|
271
273
|
with ExcelWriter(path=path) as excel_writer:
|
|
272
274
|
self.df.to_excel(
|
|
@@ -379,21 +381,22 @@ class DataframeUtilsAccessor(object):
|
|
|
379
381
|
return to_datetime(series, format=date_format).dt.date
|
|
380
382
|
elif datetime_type == "time":
|
|
381
383
|
return to_datetime(series, format=time_format).dt.time
|
|
382
|
-
|
|
383
|
-
|
|
384
|
+
|
|
385
|
+
raise ValueError(f"Unknown datetime_type: {datetime_type}")
|
|
384
386
|
|
|
385
387
|
for col, dtype in mapper.items():
|
|
386
388
|
try:
|
|
387
389
|
self.df[col] = (
|
|
388
390
|
convert_datetime(
|
|
389
|
-
series=self.df[col],
|
|
391
|
+
series=self.df.loc[:, col],
|
|
390
392
|
datetime_type=dtype, # type: ignore
|
|
391
393
|
)
|
|
392
394
|
if dtype in ["datetime", "date", "time"]
|
|
393
|
-
else to_numeric(self.df[col])
|
|
395
|
+
else to_numeric(self.df.loc[:, col])
|
|
394
396
|
if dtype == "numeric"
|
|
395
|
-
else self.df[col].astype(dtype) # type: ignore
|
|
397
|
+
else self.df.loc[:, col].astype(dtype) # type: ignore
|
|
396
398
|
)
|
|
399
|
+
|
|
397
400
|
except (
|
|
398
401
|
KeyError,
|
|
399
402
|
ValueError,
|
|
@@ -268,7 +268,7 @@ class DateTime(BaseDateTime):
|
|
|
268
268
|
)
|
|
269
269
|
|
|
270
270
|
@classmethod
|
|
271
|
-
def
|
|
271
|
+
def as_naive(
|
|
272
272
|
cls,
|
|
273
273
|
year: int,
|
|
274
274
|
month: int,
|
|
@@ -390,13 +390,15 @@ class Interval(BaseInterval):
|
|
|
390
390
|
def start(
|
|
391
391
|
self,
|
|
392
392
|
) -> DateTime:
|
|
393
|
-
return
|
|
393
|
+
return DateTime.from_base(super().start)
|
|
394
|
+
# return self._start if not (self._invert and self._absolute) else self._end
|
|
394
395
|
|
|
395
396
|
@property
|
|
396
397
|
def end(
|
|
397
398
|
self,
|
|
398
399
|
) -> DateTime:
|
|
399
|
-
return
|
|
400
|
+
return DateTime.from_base(super().end)
|
|
401
|
+
# return self._end if not (self._invert and self._absolute) else self._start
|
|
400
402
|
|
|
401
403
|
@classmethod
|
|
402
404
|
def from_base(
|
|
@@ -440,8 +442,8 @@ class Intervals(object):
|
|
|
440
442
|
def sort(
|
|
441
443
|
self,
|
|
442
444
|
) -> Self:
|
|
443
|
-
self.intervals =
|
|
444
|
-
self.intervals, key=lambda interval: (interval.start, interval.end)
|
|
445
|
+
self.intervals = tuple(
|
|
446
|
+
sorted(self.intervals, key=lambda interval: (interval.start, interval.end))
|
|
445
447
|
)
|
|
446
448
|
|
|
447
449
|
return self
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from math import isqrt, ceil
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Literal, Optional, Self, final
|
|
4
|
+
from typing import Any, Literal, Optional, Self, final
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
6
|
from mayutils.export.images import IMAGES_FOLDER
|
|
7
7
|
import numpy as np
|
|
@@ -14,7 +14,7 @@ from plotly._subplots import _build_subplot_title_annotations
|
|
|
14
14
|
|
|
15
15
|
from mayutils.objects.colours import TRANSPARENT, Colour
|
|
16
16
|
|
|
17
|
-
from mayutils.objects.functions import
|
|
17
|
+
from mayutils.objects.functions import set_inline
|
|
18
18
|
|
|
19
19
|
from mayutils.visualisation.graphs.plotly.templates import (
|
|
20
20
|
non_primary_axis_dict,
|
|
@@ -217,7 +217,6 @@ class SubPlotConfig:
|
|
|
217
217
|
cls,
|
|
218
218
|
plots: tuple[Optional[PlotConfig], ...],
|
|
219
219
|
cols: Optional[int],
|
|
220
|
-
*args,
|
|
221
220
|
**kwargs,
|
|
222
221
|
) -> "SubPlotConfig":
|
|
223
222
|
if cols is None:
|
|
@@ -232,7 +231,6 @@ class SubPlotConfig:
|
|
|
232
231
|
tuple(extended_plots[idx : idx + cols])
|
|
233
232
|
for idx in range(0, len(extended_plots), cols)
|
|
234
233
|
),
|
|
235
|
-
*args,
|
|
236
234
|
**kwargs,
|
|
237
235
|
)
|
|
238
236
|
|
|
@@ -588,7 +586,7 @@ class Plot(go.Figure):
|
|
|
588
586
|
*args,
|
|
589
587
|
**kwargs,
|
|
590
588
|
) -> Self:
|
|
591
|
-
self.data = []
|
|
589
|
+
self.data: list[Trace] = []
|
|
592
590
|
|
|
593
591
|
return self
|
|
594
592
|
|
|
@@ -707,7 +705,11 @@ class Plot(go.Figure):
|
|
|
707
705
|
**kwargs,
|
|
708
706
|
)
|
|
709
707
|
|
|
710
|
-
return
|
|
708
|
+
return (
|
|
709
|
+
IMAGES_FOLDER / f"{filename}.{image_formats[0]}"
|
|
710
|
+
if len(image_formats) > 0
|
|
711
|
+
else IMAGES_FOLDER
|
|
712
|
+
)
|
|
711
713
|
|
|
712
714
|
def modifications(
|
|
713
715
|
self,
|
|
@@ -729,7 +731,7 @@ class Plot(go.Figure):
|
|
|
729
731
|
opacity = 0.1 if trace.meta == "ecdf" else 0.4 # type: ignore
|
|
730
732
|
trace.fillcolor = colour.to_str(opacity=opacity) # type: ignore
|
|
731
733
|
|
|
732
|
-
bound_groups = {}
|
|
734
|
+
bound_groups: dict[str, tuple[tuple[Optional[str], int], list[Trace]]] = {}
|
|
733
735
|
for idx, trace in enumerate(self.data):
|
|
734
736
|
if (
|
|
735
737
|
hasattr(trace, "legendgroup")
|
|
@@ -737,7 +739,7 @@ class Plot(go.Figure):
|
|
|
737
739
|
and trace.legendgroup.startswith("bounds") # type: ignore
|
|
738
740
|
):
|
|
739
741
|
if trace.legendgroup not in bound_groups: # type: ignore
|
|
740
|
-
bound_groups[trace.legendgroup] =
|
|
742
|
+
bound_groups[trace.legendgroup] = ((None, 0), []) # type: ignore
|
|
741
743
|
|
|
742
744
|
if trace.fill == "toself": # type: ignore
|
|
743
745
|
bound_groups[trace.legendgroup][1].append(trace) # type: ignore
|
|
@@ -750,7 +752,7 @@ class Plot(go.Figure):
|
|
|
750
752
|
colour=shuffled_colourscale[idx % len(shuffled_colourscale)]
|
|
751
753
|
)
|
|
752
754
|
|
|
753
|
-
opacity = Colour.parse(colour=bound_traces[0].fillcolor).a
|
|
755
|
+
opacity = Colour.parse(colour=bound_traces[0].fillcolor).a # type: ignore
|
|
754
756
|
for bound_trace in bound_traces:
|
|
755
757
|
bound_trace.fillcolor = colour.to_str(opacity=opacity) # type: ignore
|
|
756
758
|
|
|
@@ -791,8 +793,15 @@ class Plot(go.Figure):
|
|
|
791
793
|
xaxis=self.data[idx].xaxis, # type: ignore
|
|
792
794
|
yaxis=self.data[idx].yaxis, # type: ignore
|
|
793
795
|
legendgroup=self.data[idx].legendgroup # type: ignore
|
|
794
|
-
or
|
|
795
|
-
|
|
796
|
+
or getattr(
|
|
797
|
+
set_inline(
|
|
798
|
+
self.data[idx],
|
|
799
|
+
"legendgroup",
|
|
800
|
+
idx,
|
|
801
|
+
),
|
|
802
|
+
"legendgroup",
|
|
803
|
+
idx,
|
|
804
|
+
),
|
|
796
805
|
showlegend=False,
|
|
797
806
|
label_name=False,
|
|
798
807
|
)
|
|
@@ -837,8 +846,15 @@ class Plot(go.Figure):
|
|
|
837
846
|
else f"trace {idx} Rug"
|
|
838
847
|
),
|
|
839
848
|
legendgroup=self.data[idx].legendgroup # type: ignore
|
|
840
|
-
or
|
|
841
|
-
|
|
849
|
+
or getattr(
|
|
850
|
+
set_inline(
|
|
851
|
+
self.data[idx],
|
|
852
|
+
"legendgroup",
|
|
853
|
+
idx,
|
|
854
|
+
),
|
|
855
|
+
"legendgroup",
|
|
856
|
+
idx,
|
|
857
|
+
),
|
|
842
858
|
showlegend=False,
|
|
843
859
|
marker=dict(
|
|
844
860
|
color=self.data[idx].marker.line.color, # type: ignore
|
|
@@ -862,8 +878,15 @@ class Plot(go.Figure):
|
|
|
862
878
|
else f"trace {idx} Rug"
|
|
863
879
|
),
|
|
864
880
|
legendgroup=self.data[idx].legendgroup # type: ignore
|
|
865
|
-
or
|
|
866
|
-
|
|
881
|
+
or getattr(
|
|
882
|
+
set_inline(
|
|
883
|
+
self.data[idx],
|
|
884
|
+
"legendgroup",
|
|
885
|
+
idx,
|
|
886
|
+
),
|
|
887
|
+
"legendgroup",
|
|
888
|
+
idx,
|
|
889
|
+
),
|
|
867
890
|
showlegend=False,
|
|
868
891
|
line=dict(
|
|
869
892
|
color=TRANSPARENT.to_str(),
|
|
@@ -898,8 +921,15 @@ class Plot(go.Figure):
|
|
|
898
921
|
else f"trace {idx} Rug"
|
|
899
922
|
),
|
|
900
923
|
legendgroup=self.data[idx].legendgroup # type: ignore
|
|
901
|
-
or
|
|
902
|
-
|
|
924
|
+
or getattr(
|
|
925
|
+
set_inline(
|
|
926
|
+
self.data[idx],
|
|
927
|
+
"legendgroup",
|
|
928
|
+
idx,
|
|
929
|
+
),
|
|
930
|
+
"legendgroup",
|
|
931
|
+
idx,
|
|
932
|
+
),
|
|
903
933
|
showlegend=False,
|
|
904
934
|
line=dict(
|
|
905
935
|
color=self.data[idx].marker.line.color, # type: ignore
|
|
@@ -933,8 +963,15 @@ class Plot(go.Figure):
|
|
|
933
963
|
else f"trace {idx} Rug"
|
|
934
964
|
),
|
|
935
965
|
legendgroup=self.data[idx].legendgroup # type: ignore
|
|
936
|
-
or
|
|
937
|
-
|
|
966
|
+
or getattr(
|
|
967
|
+
set_inline(
|
|
968
|
+
self.data[idx],
|
|
969
|
+
"legendgroup",
|
|
970
|
+
idx,
|
|
971
|
+
),
|
|
972
|
+
"legendgroup",
|
|
973
|
+
idx,
|
|
974
|
+
),
|
|
938
975
|
showlegend=False,
|
|
939
976
|
line=dict(
|
|
940
977
|
color=self.data[idx].marker.line.color, # type: ignore
|
|
@@ -968,8 +1005,15 @@ class Plot(go.Figure):
|
|
|
968
1005
|
else f"trace {idx} Rug"
|
|
969
1006
|
),
|
|
970
1007
|
legendgroup=self.data[idx].legendgroup # type: ignore
|
|
971
|
-
or
|
|
972
|
-
|
|
1008
|
+
or getattr(
|
|
1009
|
+
set_inline(
|
|
1010
|
+
self.data[idx],
|
|
1011
|
+
"legendgroup",
|
|
1012
|
+
idx,
|
|
1013
|
+
),
|
|
1014
|
+
"legendgroup",
|
|
1015
|
+
idx,
|
|
1016
|
+
),
|
|
973
1017
|
showlegend=False,
|
|
974
1018
|
line=dict(
|
|
975
1019
|
color=self.data[idx].marker.line.color, # type: ignore
|
|
@@ -1096,8 +1140,15 @@ class Plot(go.Figure):
|
|
|
1096
1140
|
xaxis=self.data[idx].xaxis, # type: ignore
|
|
1097
1141
|
yaxis=self.data[idx].yaxis, # type: ignore
|
|
1098
1142
|
legendgroup=self.data[idx].legendgroup # type: ignore
|
|
1099
|
-
or
|
|
1100
|
-
|
|
1143
|
+
or getattr(
|
|
1144
|
+
set_inline(
|
|
1145
|
+
self.data[idx],
|
|
1146
|
+
"legendgroup",
|
|
1147
|
+
idx,
|
|
1148
|
+
),
|
|
1149
|
+
"legendgroup",
|
|
1150
|
+
idx,
|
|
1151
|
+
),
|
|
1101
1152
|
showlegend=False,
|
|
1102
1153
|
label_name=False,
|
|
1103
1154
|
)
|
|
@@ -1107,7 +1158,7 @@ class Plot(go.Figure):
|
|
|
1107
1158
|
"layout": dict(),
|
|
1108
1159
|
},
|
|
1109
1160
|
}
|
|
1110
|
-
buttons = {
|
|
1161
|
+
buttons: dict[str, list[dict[str, Any]]] = {
|
|
1111
1162
|
"scatter": [
|
|
1112
1163
|
dict(
|
|
1113
1164
|
label="Toggle Density",
|
|
@@ -1482,6 +1533,8 @@ class SubPlot(Plot):
|
|
|
1482
1533
|
if is_scene:
|
|
1483
1534
|
scene_count += 1
|
|
1484
1535
|
scene_str = str(scene_count) if scene_count != 1 else ""
|
|
1536
|
+
else:
|
|
1537
|
+
scene_str = ""
|
|
1485
1538
|
|
|
1486
1539
|
xaxis_num = (
|
|
1487
1540
|
col_idx + row_idx * len(subplot_config.plots[0]) + 1 - scene_count
|
|
@@ -1588,12 +1641,17 @@ class SubPlot(Plot):
|
|
|
1588
1641
|
|
|
1589
1642
|
self.modifications()
|
|
1590
1643
|
|
|
1591
|
-
def add_rug(
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1644
|
+
# def add_rug(
|
|
1645
|
+
# self,
|
|
1646
|
+
# rug_type: Literal[
|
|
1647
|
+
# "scatter", "violin", "box", "strip", "historgram", "ecdf"
|
|
1648
|
+
# ] = "scatter",
|
|
1649
|
+
# rug_height: Optional[float] = None,
|
|
1650
|
+
# *args,
|
|
1651
|
+
# **kwargs,
|
|
1652
|
+
# ) -> Self:
|
|
1653
|
+
# raise NotImplementedError("Rug not implemented for SubPlot")
|
|
1654
|
+
# return self
|
|
1597
1655
|
|
|
1598
1656
|
|
|
1599
1657
|
def pop_axis_config_title(
|
|
@@ -1641,7 +1699,7 @@ def get_domains(
|
|
|
1641
1699
|
def sort_traces_by_axes(
|
|
1642
1700
|
traces: list[Trace],
|
|
1643
1701
|
) -> dict:
|
|
1644
|
-
traces_axes = {}
|
|
1702
|
+
traces_axes: dict[tuple[str, str], list[Trace]] = {}
|
|
1645
1703
|
for trace in traces:
|
|
1646
1704
|
if (trace.xaxis, trace.yaxis) in traces_axes: # type: ignore
|
|
1647
1705
|
traces_axes[(trace.xaxis, trace.yaxis)].append(trace) # type: ignore
|
|
@@ -259,7 +259,7 @@ class Icicle(go.Icicle):
|
|
|
259
259
|
if path in node_values:
|
|
260
260
|
return node_values[path]
|
|
261
261
|
|
|
262
|
-
total = 0
|
|
262
|
+
total = 0.0
|
|
263
263
|
for key, value in d.items():
|
|
264
264
|
new_path = f"{path}/{key}" if path else key
|
|
265
265
|
if isinstance(value, dict):
|
|
@@ -470,7 +470,6 @@ class Bar3d(go.Mesh3d):
|
|
|
470
470
|
value_weights: bool = False,
|
|
471
471
|
x_mapping: Optional[ArrayLike] = None,
|
|
472
472
|
y_mapping: Optional[ArrayLike] = None,
|
|
473
|
-
*args,
|
|
474
473
|
**kwargs,
|
|
475
474
|
) -> Self:
|
|
476
475
|
if not df.columns.is_unique:
|
|
@@ -490,7 +489,6 @@ class Bar3d(go.Mesh3d):
|
|
|
490
489
|
y=y,
|
|
491
490
|
z=z,
|
|
492
491
|
w=z if value_weights else kwargs.pop("w", None),
|
|
493
|
-
*args,
|
|
494
492
|
**kwargs,
|
|
495
493
|
)
|
|
496
494
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|