tesorotools-python 0.0.14__tar.gz → 0.0.15__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 (52) hide show
  1. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/PKG-INFO +1 -1
  2. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/pyproject.toml +1 -1
  3. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/convert.py +9 -3
  4. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/render/__init__.py +4 -0
  5. tesorotools_python-0.0.14/tesorotools/render/introduction.py → tesorotools_python-0.0.15/tesorotools/render/content/subtitle.py +8 -4
  6. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/render/content/table.py +21 -12
  7. tesorotools_python-0.0.14/tesorotools/render/headline.py → tesorotools_python-0.0.15/tesorotools/render/content/title.py +8 -8
  8. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/render/report.py +3 -1
  9. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/.gitignore +0 -0
  10. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/__init__.py +0 -0
  11. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/artists/__init__.py +0 -0
  12. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/artists/barh_plot.py +0 -0
  13. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/artists/line_plot.py +0 -0
  14. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/artists/table.py +0 -0
  15. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/artists/type_curve.py +0 -0
  16. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/README.md +0 -0
  17. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/fonts/CabinetGrotesk-Black.otf +0 -0
  18. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/fonts/CabinetGrotesk-Bold.otf +0 -0
  19. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/fonts/CabinetGrotesk-Extrabold.otf +0 -0
  20. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/fonts/CabinetGrotesk-Extralight.otf +0 -0
  21. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/fonts/CabinetGrotesk-Light.otf +0 -0
  22. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/fonts/CabinetGrotesk-Medium.otf +0 -0
  23. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/fonts/CabinetGrotesk-Regular.otf +0 -0
  24. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/fonts/CabinetGrotesk-Thin.otf +0 -0
  25. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/fonts/README.md +0 -0
  26. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/plots.yaml +0 -0
  27. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/assets/tesoro.mplstyle +0 -0
  28. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/data_sources/README.md +0 -0
  29. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/data_sources/__init__.py +0 -0
  30. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/data_sources/debug.py +0 -0
  31. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/data_sources/lseg.py +0 -0
  32. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/database/__init__.py +0 -0
  33. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/database/push.py +0 -0
  34. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/dependencies/__init__.py +0 -0
  35. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/dependencies/functions.py +0 -0
  36. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/dependencies/node.py +0 -0
  37. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/dependencies/resolution.py +0 -0
  38. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/main.py +0 -0
  39. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/offsets/__init__.py +0 -0
  40. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/offsets/offsets.py +0 -0
  41. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/offsets/outliers.py +0 -0
  42. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/render/content/__init__.py +0 -0
  43. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/render/content/content.py +0 -0
  44. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/render/content/images.py +0 -0
  45. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/render/content/section.py +0 -0
  46. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/render/content/text.py +0 -0
  47. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/utils/__init__.py +0 -0
  48. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/utils/config.py +0 -0
  49. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/utils/globals.py +0 -0
  50. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/utils/matplotlib.py +0 -0
  51. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/utils/series.py +0 -0
  52. {tesorotools_python-0.0.14 → tesorotools_python-0.0.15}/tesorotools/utils/template.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tesorotools-python
3
- Version: 0.0.14
3
+ Version: 0.0.15
4
4
  Requires-Dist: babel
5
5
  Requires-Dist: eikon
6
6
  Requires-Dist: lseg-data
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tesorotools-python"
3
- version = "0.0.14"
3
+ version = "0.0.15"
4
4
  dependencies = ["psycopg2", "SQLAlchemy", "pandas", "matplotlib", "pyarrow", "python-docx", "openpyxl", "PyYAML", "babel", "eikon", "lseg-data"]
5
5
 
6
6
  [build-system]
@@ -37,13 +37,19 @@ def cheap_convert(old_file: Path) -> pd.DataFrame:
37
37
  trimmed = old.loc[(slice(None), "no", "absolute", "value"), :].copy()
38
38
 
39
39
  old = old.loc[
40
- (slice(None), ["day", "mtd", "week", "year"], slice(None), slice(None)),
40
+ (
41
+ slice(None),
42
+ ["day", "mtd", "week", "year", "tariff_crisis"],
43
+ slice(None),
44
+ slice(None),
45
+ ),
41
46
  :,
42
47
  ]
43
48
  old.index = index_replace("day", "bday", old.index)
44
49
  old.index = index_replace("week", "ftd", old.index)
45
50
  old.index = index_replace("year", "ytd", old.index)
46
51
  old.index = index_replace("roll_var", "roll_std", old.index)
52
+ old.index = index_replace("tariff_crisis", "2025-04-02", old.index)
47
53
 
48
54
  trimmed.index = index_replace("absolute", "no", trimmed.index)
49
55
 
@@ -52,7 +58,7 @@ def cheap_convert(old_file: Path) -> pd.DataFrame:
52
58
 
53
59
 
54
60
  if __name__ == "__main__":
55
- preprocess = False
61
+ preprocess = True
56
62
  barh_config_dicts = read_config(Path("examples") / "barh_plots.yaml")
57
63
  line_config_dicts = read_config(Path("examples") / "line_plots.yaml")
58
64
  type_config_dicts = read_config(Path("examples") / "type_curves.yaml")
@@ -81,7 +87,7 @@ if __name__ == "__main__":
81
87
  independent_full_df,
82
88
  dependent_trimmed_df,
83
89
  offsets_config,
84
- force_trim=True,
90
+ # force_trim=True,
85
91
  )
86
92
  full_df.to_feather("derivates.feather")
87
93
 
@@ -1,7 +1,9 @@
1
1
  from tesorotools.render.content.images import Image, Images
2
2
  from tesorotools.render.content.section import Section
3
+ from tesorotools.render.content.subtitle import Subtitle
3
4
  from tesorotools.render.content.table import Table
4
5
  from tesorotools.render.content.text import Text
6
+ from tesorotools.render.content.title import Title
5
7
  from tesorotools.render.report import Report
6
8
  from tesorotools.utils.template import TemplateLoader
7
9
 
@@ -11,3 +13,5 @@ TemplateLoader.add_constructor("!image", Image.from_yaml)
11
13
  TemplateLoader.add_constructor("!images", Images.from_yaml)
12
14
  TemplateLoader.add_constructor("!table", Table.from_yaml)
13
15
  TemplateLoader.add_constructor("!text", Text.from_yaml)
16
+ TemplateLoader.add_constructor("!title", Title.from_yaml)
17
+ TemplateLoader.add_constructor("!subtitle", Subtitle.from_yaml)
@@ -3,18 +3,22 @@ from typing import Any, Self
3
3
 
4
4
  from babel.dates import format_datetime
5
5
  from docx.document import Document
6
+ from yaml import MappingNode
6
7
 
8
+ from tesorotools.utils.config import TemplateLoader
7
9
 
8
- class Introduction:
10
+
11
+ class Subtitle:
9
12
  def __init__(self, date_time: datetime | None = None) -> None:
10
13
  if date_time is None:
11
14
  date_time: datetime = datetime.now()
12
15
  self._date_time: datetime = date_time
13
16
 
14
17
  @classmethod
15
- def from_dict(cls, introduction_cfg: dict[str, Any]) -> Self:
18
+ def from_yaml(cls, loader: TemplateLoader, node: MappingNode) -> Self:
19
+ subtitle_cfg: dict[str, Any] = loader.construct_mapping(node, deep=True)
16
20
  # parse date
17
- date_cfg: str | date | None = introduction_cfg.get("date", None)
21
+ date_cfg: str | date | None = subtitle_cfg.get("date", None)
18
22
  if date_cfg is None:
19
23
  date_time: datetime = datetime.now()
20
24
  elif isinstance(date_cfg, date):
@@ -23,7 +27,7 @@ class Introduction:
23
27
  date_time: datetime = datetime.strptime(date_cfg, "%Y-%m-%d")
24
28
 
25
29
  # parse hour
26
- hour_cfg: str | None = introduction_cfg.get("hour", None)
30
+ hour_cfg: str | None = subtitle_cfg.get("hour", None)
27
31
  if hour_cfg is not None:
28
32
  hour_str, minute_str = hour_cfg.split(sep=":")
29
33
  date_time = date_time.replace(
@@ -4,12 +4,12 @@ from typing import Any, Self
4
4
  import numpy as np
5
5
  import pandas as pd
6
6
  from docx.document import Document
7
- from docx.enum.table import WD_ALIGN_VERTICAL
7
+ from docx.enum.table import WD_ALIGN_VERTICAL, WD_TABLE_ALIGNMENT
8
8
  from docx.enum.text import WD_ALIGN_PARAGRAPH
9
9
  from docx.oxml import OxmlElement, parse_xml
10
10
  from docx.oxml.ns import nsdecls, qn
11
11
  from docx.shared import Inches, Pt, RGBColor
12
- from docx.table import Table
12
+ from docx.table import Table as TableDocx
13
13
  from docx.table import _Cell as TableCell
14
14
  from yaml import MappingNode
15
15
 
@@ -69,7 +69,7 @@ def _style_horizontal_blocks_header(cell: TableCell):
69
69
  cell.paragraphs[0].runs[0].font.size = Pt(12)
70
70
 
71
71
 
72
- def _horizontal_blocks_header(columns: pd.MultiIndex, table_docx: Table):
72
+ def _horizontal_blocks_header(columns: pd.MultiIndex, table_docx: TableDocx):
73
73
  column_counter: int = 1
74
74
  blocks: list[str] = list(columns.get_level_values(level=0).unique())
75
75
  for block in blocks:
@@ -92,7 +92,7 @@ def _style_column_names(cell: TableCell):
92
92
 
93
93
 
94
94
  def _fill_column_names(
95
- table: pd.DataFrame, table_docx: Table, horizontal: bool
95
+ table: pd.DataFrame, table_docx: TableDocx, horizontal: bool
96
96
  ):
97
97
  if horizontal:
98
98
  start_row: int = 1
@@ -115,13 +115,13 @@ def _style_index_names(cell: TableCell):
115
115
 
116
116
 
117
117
  def _fill_index_names(
118
- index: pd.Index | pd.MultiIndex, table_docx: Table, horizontal: bool
118
+ index: pd.Index | pd.MultiIndex, table_docx: TableDocx, horizontal: bool
119
119
  ):
120
120
  start_row: int = 2 if horizontal else 1
121
121
 
122
122
  index_names: pd.Index = (
123
123
  index
124
- if (horizontal or isinstance(index, pd.Index))
124
+ if (horizontal or (not isinstance(index, pd.MultiIndex)))
125
125
  else index.get_level_values(level=1)
126
126
  )
127
127
 
@@ -132,7 +132,7 @@ def _fill_index_names(
132
132
 
133
133
 
134
134
  # we only separate blocks in vertically stacked tables
135
- def _separate_blocks(index: pd.MultiIndex, table_docx: Table):
135
+ def _separate_blocks(index: pd.MultiIndex, table_docx: TableDocx):
136
136
  blocks: list[str] = list(index.get_level_values(level=0).unique())
137
137
  previous_rows = 0
138
138
  for block in blocks[:-1]:
@@ -186,7 +186,7 @@ def _fill_content(
186
186
  table: pd.DataFrame,
187
187
  color_table: pd.DataFrame,
188
188
  shade_table: pd.DataFrame,
189
- table_docx: Table,
189
+ table_docx: TableDocx,
190
190
  horizontal: bool,
191
191
  ):
192
192
  start_row: int = 2 if horizontal else 1
@@ -209,7 +209,7 @@ def _fill_content(
209
209
  _style_content(cell)
210
210
 
211
211
 
212
- def _style_table(table_docx: Table):
212
+ def _style_table(table_docx: TableDocx):
213
213
  table_docx.style = RENDER_CONFIG.get("style", None)
214
214
  table_docx.autofit = RENDER_CONFIG["autofit"]
215
215
 
@@ -221,10 +221,10 @@ def render_table(
221
221
  document: Document,
222
222
  block_sep: bool,
223
223
  **kwargs,
224
- ) -> Table:
224
+ ) -> TableDocx:
225
225
 
226
226
  horizontal: bool = isinstance(table.columns, pd.MultiIndex)
227
- table_docx: Table = document.add_table(
227
+ table_docx: TableDocx = document.add_table(
228
228
  rows=len(table.index) + table.columns.nlevels,
229
229
  cols=len(table.columns) + 1,
230
230
  )
@@ -237,6 +237,7 @@ def render_table(
237
237
  if block_sep:
238
238
  _separate_blocks(table.index, table_docx)
239
239
  _fill_content(table, color_table, shade_table, table_docx, horizontal)
240
+ table_docx.alignment = WD_TABLE_ALIGNMENT.CENTER
240
241
  return document
241
242
 
242
243
 
@@ -274,7 +275,15 @@ class Table:
274
275
  table_cfg: dict[str, Any] = loader.construct_mapping(node, deep=True)
275
276
  root_path: Path = loader.imports["table"]
276
277
  file_prefix: str = table_cfg.pop("id")
277
- data_file: Path = root_path / f"{file_prefix}_data.feather"
278
+
279
+ # the data file has an optional "_data" suffix
280
+ # if a file with the suffix exists, it will be preferred
281
+ data_file_suffix: Path = root_path / f"{file_prefix}_data.feather"
282
+ if data_file_suffix.exists():
283
+ data_file: Path = data_file_suffix
284
+ else:
285
+ data_file: Path = root_path / f"{file_prefix}.feather"
286
+
278
287
  color_file: Path = root_path / f"{file_prefix}_color.feather"
279
288
  shade_file: Path = root_path / f"{file_prefix}_shade.feather"
280
289
  return cls(
@@ -1,9 +1,12 @@
1
1
  from typing import Any, Self
2
2
 
3
3
  from docx.document import Document
4
+ from yaml import MappingNode
4
5
 
6
+ from tesorotools.utils.config import TemplateLoader
5
7
 
6
- class HeadLine:
8
+
9
+ class Title:
7
10
  def __init__(
8
11
  self, title: str | None = None, comment: str | None = None
9
12
  ) -> None:
@@ -11,9 +14,10 @@ class HeadLine:
11
14
  self._comment: str = "" if comment is None else comment
12
15
 
13
16
  @classmethod
14
- def from_dict(cls, headline_cfg: dict[str, Any]) -> Self:
15
- title: str | None = headline_cfg.get("title", None)
16
- comment: str | None = headline_cfg.get("comment", None)
17
+ def from_yaml(cls, loader: TemplateLoader, node: MappingNode) -> Self:
18
+ title_cfg: dict[str, Any] = loader.construct_mapping(node, deep=True)
19
+ title: str | None = title_cfg.get("title", None)
20
+ comment: str | None = title_cfg.get("comment", None)
17
21
  return cls(title, comment)
18
22
 
19
23
  def render(self, document: Document) -> Document:
@@ -31,10 +35,6 @@ class HeadLine:
31
35
  def title(self) -> str:
32
36
  return self._title
33
37
 
34
- @title.setter
35
- def title(self, title) -> None:
36
- self._title = title
37
-
38
38
  @property
39
39
  def comment(self) -> str:
40
40
  return self._comment
@@ -4,6 +4,7 @@ from docx.document import Document
4
4
  from yaml import Loader, MappingNode
5
5
 
6
6
  from tesorotools.render.content.content import Content
7
+ from tesorotools.render.content.title import Title
7
8
 
8
9
 
9
10
  class Report:
@@ -25,5 +26,6 @@ class Report:
25
26
  document._body.clear_content()
26
27
  for _, content in self.contents.items():
27
28
  content.render(document)
28
- document.add_paragraph()
29
+ if not isinstance(content, Title):
30
+ document.add_paragraph()
29
31
  return document