mayutils 1.2.6__tar.gz → 1.2.8__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.
Files changed (64) hide show
  1. {mayutils-1.2.6 → mayutils-1.2.8}/PKG-INFO +1 -1
  2. {mayutils-1.2.6 → mayutils-1.2.8}/pyproject.toml +1 -1
  3. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/data/queries/__init__.py +7 -2
  4. mayutils-1.2.8/src/mayutils/data/read.py +86 -0
  5. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/environment/memoisation.py +3 -1
  6. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/dataframes.py +62 -1
  7. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/datetime.py +11 -1
  8. mayutils-1.2.6/src/mayutils/data/read.py +0 -61
  9. {mayutils-1.2.6 → mayutils-1.2.8}/LICENSE +0 -0
  10. {mayutils-1.2.6 → mayutils-1.2.8}/README.md +0 -0
  11. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/__init__.py +0 -0
  12. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/core/__init__.py +0 -0
  13. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/core/constants.py +0 -0
  14. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/data/__init__.py +0 -0
  15. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/data/analysis/__init__.py +0 -0
  16. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/data/cache/.gitkeep +0 -0
  17. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/data/live.py +0 -0
  18. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/data/local.py +0 -0
  19. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/data/queries/.gitkeep +0 -0
  20. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/data/queries/examples/.gitkeep +0 -0
  21. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/environment/__init__.py +0 -0
  22. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/environment/benchmarking.py +0 -0
  23. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/environment/databases.py +0 -0
  24. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/environment/filesystem.py +0 -0
  25. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/environment/logging.py +0 -0
  26. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/environment/oauth.py +0 -0
  27. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/environment/webdrivers.py +0 -0
  28. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/export/__init__.py +0 -0
  29. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/export/images.py +0 -0
  30. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/export/pdf.py +0 -0
  31. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/export/slides.py +0 -0
  32. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/interfaces/__init__.py +0 -0
  33. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/interfaces/google.py +0 -0
  34. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/interfaces/microsoft.py +0 -0
  35. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/interfaces/streamlit.py +0 -0
  36. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/mathematics/__init__.py +0 -0
  37. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/mathematics/numba.py +0 -0
  38. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/mathematics/numpy.py +0 -0
  39. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/__init__.py +0 -0
  40. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/classes.py +0 -0
  41. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/colours.py +0 -0
  42. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/decorators.py +0 -0
  43. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/dictionaries.py +0 -0
  44. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/functions.py +0 -0
  45. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/hashing.py +0 -0
  46. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/numbers.py +0 -0
  47. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/strings.py +0 -0
  48. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/objects/types.py +0 -0
  49. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/scripts/__init__.py +0 -0
  50. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/scripts/clear_cache.py +0 -0
  51. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/scripts/versioning.py +0 -0
  52. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/testing/__init__.py +0 -0
  53. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/visualisation/__init__.py +0 -0
  54. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/visualisation/console.py +0 -0
  55. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/visualisation/graphs/__init__.py +0 -0
  56. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/visualisation/graphs/combine.py +0 -0
  57. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/visualisation/graphs/matplotlib/__init__.py +0 -0
  58. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/visualisation/graphs/matplotlib/template.py +0 -0
  59. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/visualisation/graphs/plotly/__init__.py +0 -0
  60. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/visualisation/graphs/plotly/charts.py +0 -0
  61. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/visualisation/graphs/plotly/templates.py +0 -0
  62. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/visualisation/graphs/plotly/traces.py +0 -0
  63. {mayutils-1.2.6 → mayutils-1.2.8}/src/mayutils/visualisation/graphs/plotly/utilities.py +0 -0
  64. {mayutils-1.2.6 → mayutils-1.2.8}/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.6
3
+ Version: 1.2.8
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>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mayutils"
3
- version = "1.2.6"
3
+ version = "1.2.8"
4
4
  description = "Utilities for Python from Mayuran Visakan"
5
5
  authors = [
6
6
  { name = "Mayuran Visakan", email = "mayuran.k.v@gmail.com" }
@@ -24,7 +24,7 @@ QUERIES_FOLDERS = get_queries_folders()
24
24
 
25
25
  def get_query(
26
26
  query_name: Path | str,
27
- queries_folders: tuple[Path, ...],
27
+ queries_folders: tuple[Path, ...] = QUERIES_FOLDERS,
28
28
  ) -> str:
29
29
  path = Path(query_name)
30
30
  for queries_folder in queries_folders:
@@ -33,7 +33,12 @@ def get_query(
33
33
  except ValueError:
34
34
  continue
35
35
 
36
- return read_file(path=path)
36
+ try:
37
+ return read_file(path=path)
38
+ except ValueError:
39
+ raise ValueError(
40
+ f"No such query {query_name} found in the query folders {', '.join(list(map(str, queries_folders)))} or at the path {path}"
41
+ )
37
42
 
38
43
 
39
44
  def get_formatted_query(
@@ -0,0 +1,86 @@
1
+ from functools import _lru_cache_wrapper
2
+ from pathlib import Path
3
+ from typing import Literal, overload
4
+
5
+ from pandas import DataFrame
6
+ import polars as pl
7
+
8
+ from mayutils.data import CACHE_FOLDER
9
+ from mayutils.data.queries import QUERIES_FOLDERS, get_formatted_query
10
+ from mayutils.environment.filesystem import encode_path
11
+ from mayutils.environment.memoisation import DataframeBackends
12
+ from mayutils.objects.dataframes import DataFrames, read_parquet, to_parquet
13
+ from mayutils.objects.hashing import hash_inputs
14
+
15
+
16
+ @overload
17
+ def get_query_data(
18
+ query_name: Path | str,
19
+ read_query: _lru_cache_wrapper[DataFrames],
20
+ dataframe_backend: Literal["pandas"],
21
+ queries_folders: tuple[Path, ...] = QUERIES_FOLDERS,
22
+ cache: bool | Literal["persistent"] = True,
23
+ **format_kwargs,
24
+ ) -> DataFrame: ...
25
+
26
+
27
+ @overload
28
+ def get_query_data(
29
+ query_name: Path | str,
30
+ read_query: _lru_cache_wrapper[DataFrames],
31
+ dataframe_backend: Literal["polars"],
32
+ queries_folders: tuple[Path, ...] = QUERIES_FOLDERS,
33
+ cache: bool | Literal["persistent"] = True,
34
+ **format_kwargs,
35
+ ) -> pl.DataFrame: ...
36
+
37
+
38
+ def get_query_data(
39
+ query_name: Path | str,
40
+ read_query: _lru_cache_wrapper[DataFrames],
41
+ dataframe_backend: DataframeBackends = "pandas",
42
+ queries_folders: tuple[Path, ...] = QUERIES_FOLDERS,
43
+ cache: bool | Literal["persistent"] = True,
44
+ **format_kwargs,
45
+ ) -> DataFrames:
46
+ if (
47
+ cache is False
48
+ and hasattr(read_query, "cache_clear")
49
+ and callable(getattr(read_query, "cache_clear"))
50
+ ):
51
+ read_query.cache_clear()
52
+
53
+ cache_name = f"{encode_path(path=query_name)}_data_{
54
+ hash_inputs(
55
+ query_name=query_name,
56
+ **format_kwargs,
57
+ )
58
+ }"
59
+ cache_file = CACHE_FOLDER / f"{cache_name}.parquet"
60
+
61
+ if cache != "persistent" or not cache_file.is_file():
62
+ query_string = get_formatted_query(
63
+ query_name=query_name,
64
+ queries_folders=queries_folders,
65
+ **format_kwargs,
66
+ )
67
+
68
+ query_data = read_query(
69
+ query_string=query_string,
70
+ dataframe_backend=dataframe_backend,
71
+ )
72
+
73
+ if cache == "persistent":
74
+ to_parquet(
75
+ df=query_data,
76
+ path=cache_file,
77
+ index=True,
78
+ )
79
+
80
+ else:
81
+ query_data = read_parquet(
82
+ path=cache_file,
83
+ dataframe_backend=dataframe_backend,
84
+ )
85
+
86
+ return query_data
@@ -15,6 +15,8 @@ from mayutils.objects.hashing import hash_inputs
15
15
 
16
16
  T = TypeVar("T", bound=Callable[..., Any])
17
17
 
18
+ DataframeBackends = Literal["pandas", "polars"]
19
+
18
20
 
19
21
  @flexwrap
20
22
  class cache(object):
@@ -139,7 +141,7 @@ class cache_df(object):
139
141
  *,
140
142
  format: Literal["parquet", "csv", "feather", "xlsx"] = "parquet",
141
143
  cache_folder: Path | str = CACHE_FOLDER,
142
- dataframe_backend: Literal["pandas", "polars"] = "pandas",
144
+ dataframe_backend: DataframeBackends = "pandas",
143
145
  ) -> None:
144
146
  if func is None:
145
147
  raise ValueError("No function provided")
@@ -1,8 +1,9 @@
1
1
  from pathlib import Path
2
- from typing import Callable, Literal, Optional, Self
2
+ from typing import Callable, Literal, Optional, Self, TypeAlias, get_args
3
3
 
4
4
  from itables import show
5
5
  from great_tables import GT
6
+ import pandas as pd
6
7
  from pandas import (
7
8
  DataFrame,
8
9
  ExcelWriter,
@@ -24,10 +25,14 @@ from dataframe_image._pandas_accessor import (
24
25
  prepare_converter,
25
26
  save_image,
26
27
  )
28
+ import polars as pl
29
+ from mayutils.environment.memoisation import DataframeBackends
27
30
  import numpy as np
28
31
  from mayutils.objects.colours import Colour
29
32
  from mayutils.export import OUTPUT_FOLDER
30
33
 
34
+ DataFrames: TypeAlias = pd.DataFrame | pl.DataFrame
35
+
31
36
  DATA_FOLDER = OUTPUT_FOLDER / "Data"
32
37
 
33
38
 
@@ -524,6 +529,62 @@ class IndexUtilsAccessor(object):
524
529
  # raise TypeError(f"Unsupported DataFrame type: {type(df)}")
525
530
 
526
531
 
532
+ def to_parquet(
533
+ df: DataFrames,
534
+ path: Path | str,
535
+ dataframe_backend: Optional[DataframeBackends] = None,
536
+ **kwargs,
537
+ ) -> None:
538
+ path = Path(path)
539
+
540
+ if dataframe_backend is None:
541
+ module = type(df).__module__
542
+
543
+ if module not in get_args(DataframeBackends):
544
+ raise TypeError(f"Unsupported DataFrame type: {module}")
545
+
546
+ dataframe_backend = module # type: ignore
547
+
548
+ if dataframe_backend == "pandas":
549
+ assert isinstance(df, pd.DataFrame)
550
+
551
+ df.to_parquet(
552
+ path=path,
553
+ index=kwargs.pop("index", True),
554
+ **kwargs,
555
+ )
556
+ elif dataframe_backend == "polars":
557
+ assert isinstance(df, pl.DataFrame)
558
+
559
+ df.write_parquet(
560
+ file=path,
561
+ **kwargs,
562
+ )
563
+
564
+ raise TypeError(f"Unsupported DataFrame backend: {dataframe_backend}")
565
+
566
+
567
+ def read_parquet(
568
+ path: Path | str,
569
+ dataframe_backend: DataframeBackends = "pandas",
570
+ **kwargs,
571
+ ) -> DataFrames:
572
+ path = Path(path)
573
+
574
+ if dataframe_backend == "pandas":
575
+ return pd.read_parquet(
576
+ path=path,
577
+ **kwargs,
578
+ )
579
+ elif dataframe_backend == "polars":
580
+ return pl.read_parquet(
581
+ source=path,
582
+ **kwargs,
583
+ )
584
+
585
+ raise TypeError(f"Unsupported DataFrame backend: {dataframe_backend}")
586
+
587
+
527
588
  def setup_dataframes() -> None:
528
589
  register_dataframe_accessor(name="utils")(DataframeUtilsAccessor)
529
590
  register_series_accessor(name="utils")(SeriesUtilsAccessor)
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
  from contextlib import _GeneratorContextManager
3
3
  from sqlite3 import register_adapter
4
- from typing import Any, Iterator, Optional, Self, Literal, overload
4
+ from typing import Any, Iterator, Mapping, Optional, Self, Literal, overload
5
5
  import datetime as _datetime
6
6
  import numpy as np
7
7
  from pendulum import (
@@ -453,6 +453,16 @@ class Interval(BaseInterval):
453
453
  absolute=absolute,
454
454
  )
455
455
 
456
+ def __deepcopy__(
457
+ self,
458
+ _memo: Mapping,
459
+ ) -> Self:
460
+ return self.__class__(
461
+ start=self._start,
462
+ end=self._end,
463
+ absolute=self._absolute,
464
+ )
465
+
456
466
  @property
457
467
  def start(
458
468
  self,
@@ -1,61 +0,0 @@
1
- from functools import lru_cache
2
- from pathlib import Path
3
- from typing import Literal
4
-
5
- import pandas as pd
6
- from pandas import DataFrame
7
-
8
- from mayutils.data import CACHE_FOLDER
9
- from mayutils.data.queries import QUERIES_FOLDERS
10
- from mayutils.environment.filesystem import encode_path
11
- from mayutils.objects.hashing import hash_inputs
12
-
13
-
14
- def get_query_data(
15
- query_name: str,
16
- queries_folders: tuple[Path, ...] = QUERIES_FOLDERS,
17
- date_columns: tuple[str, ...] = tuple(),
18
- time_columns: tuple[str, ...] = tuple(),
19
- numeric_columns: tuple[str, ...] = tuple(),
20
- cache: bool | Literal["persistent"] = True,
21
- reader=None,
22
- backend: Literal["snowflake"] = "snowflake",
23
- **format_kwargs,
24
- ) -> DataFrame:
25
- if cache is False:
26
- _get_query_data.cache_clear()
27
-
28
- cache_name = f"{encode_path(path=query_name)}_data_{
29
- hash_inputs(
30
- query_name=query_name,
31
- date_columns=date_columns,
32
- time_columns=time_columns,
33
- numeric_columns=numeric_columns,
34
- **format_kwargs,
35
- )
36
- }"
37
- cache_file = CACHE_FOLDER / f"{cache_name}.parquet"
38
- if cache != "persistent" or not cache_file.is_file():
39
- query_data = _get_query_data(
40
- query_name=query_name,
41
- queries_folders=queries_folders,
42
- reader=reader,
43
- **format_kwargs,
44
- )
45
-
46
- if cache == "persistent":
47
- query_data.to_parquet(
48
- path=cache_file,
49
- index=True,
50
- )
51
- else:
52
- query_data = pd.read_parquet(
53
- path=cache_file,
54
- )
55
-
56
- return query_data
57
-
58
-
59
- @lru_cache
60
- def _get_query_data() -> DataFrame:
61
- return DataFrame()
File without changes
File without changes