rephorm 1.0.1__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.
Files changed (73) hide show
  1. rephorm/__init__.py +19 -0
  2. rephorm/decorators/__init__.py +0 -0
  3. rephorm/decorators/settings_validation.py +49 -0
  4. rephorm/dict/__init__.py +1 -0
  5. rephorm/dict/colors.py +22 -0
  6. rephorm/dict/legend_positions.py +136 -0
  7. rephorm/dict/styles.py +206 -0
  8. rephorm/dict/update_layout.py +129 -0
  9. rephorm/dict/update_traces.py +90 -0
  10. rephorm/object_mappers/__init__.py +0 -0
  11. rephorm/object_mappers/_globals.py +16 -0
  12. rephorm/object_mappers/_utilities/__init__.py +0 -0
  13. rephorm/object_mappers/_utilities/chart_mapper_utility.py +34 -0
  14. rephorm/object_mappers/_utilities/grid_mapper_utility.py +11 -0
  15. rephorm/object_mappers/_utilities/table_mapper_utility.py +59 -0
  16. rephorm/object_mappers/chapter_mapper.py +82 -0
  17. rephorm/object_mappers/chart_mapper.py +120 -0
  18. rephorm/object_mappers/chart_series_mapper.py +52 -0
  19. rephorm/object_mappers/grid_mapper.py +106 -0
  20. rephorm/object_mappers/page_break_mapper.py +8 -0
  21. rephorm/object_mappers/report_mapper.py +76 -0
  22. rephorm/object_mappers/table_mapper.py +191 -0
  23. rephorm/object_mappers/table_section_mapper.py +41 -0
  24. rephorm/object_mappers/table_series_mapper.py +79 -0
  25. rephorm/object_mappers/text_mapper.py +36 -0
  26. rephorm/object_params/__init__.py +0 -0
  27. rephorm/object_params/settings.py +184 -0
  28. rephorm/objects/__init__.py +0 -0
  29. rephorm/objects/_utilities/__init__.py +0 -0
  30. rephorm/objects/_utilities/settings_container.py +8 -0
  31. rephorm/objects/chapter.py +44 -0
  32. rephorm/objects/chart.py +70 -0
  33. rephorm/objects/chart_series.py +40 -0
  34. rephorm/objects/footnote.py +13 -0
  35. rephorm/objects/grid.py +57 -0
  36. rephorm/objects/page_break.py +13 -0
  37. rephorm/objects/report.py +196 -0
  38. rephorm/objects/table.py +76 -0
  39. rephorm/objects/table_section.py +48 -0
  40. rephorm/objects/table_series.py +36 -0
  41. rephorm/objects/text.py +35 -0
  42. rephorm/utility/PDF.py +80 -0
  43. rephorm/utility/__init__.py +0 -0
  44. rephorm/utility/add_style_prefix.py +30 -0
  45. rephorm/utility/fonts/OpenSans-Bold.ttf +0 -0
  46. rephorm/utility/fonts/OpenSans-BoldItalic.ttf +0 -0
  47. rephorm/utility/fonts/OpenSans-Italic.ttf +0 -0
  48. rephorm/utility/fonts/OpenSans.ttf +0 -0
  49. rephorm/utility/fonts/__init__.py +0 -0
  50. rephorm/utility/fonts/font_loading.py +74 -0
  51. rephorm/utility/is_set.py +9 -0
  52. rephorm/utility/merge/__init__.py +0 -0
  53. rephorm/utility/merge/chart_properties_manager.py +80 -0
  54. rephorm/utility/merge/merge_settings.py +134 -0
  55. rephorm/utility/merge/merge_styles.py +79 -0
  56. rephorm/utility/merge/pdf_merger.py +29 -0
  57. rephorm/utility/report/__init__.py +0 -0
  58. rephorm/utility/report/add_footnotes.py +46 -0
  59. rephorm/utility/report/cleanup_utility.py +19 -0
  60. rephorm/utility/report/footnotes_counter.py +15 -0
  61. rephorm/utility/report/image_utility.py +14 -0
  62. rephorm/utility/report/layout_utility.py +59 -0
  63. rephorm/utility/report/range_utility.py +94 -0
  64. rephorm/utility/report/report_utility.py +93 -0
  65. rephorm/utility/report/resolve_color.py +39 -0
  66. rephorm/utility/report/table_utility.py +71 -0
  67. rephorm/utility/report/title_utility.py +49 -0
  68. rephorm/utility/unit_converter.py +12 -0
  69. rephorm-1.0.1.dist-info/METADATA +41 -0
  70. rephorm-1.0.1.dist-info/RECORD +73 -0
  71. rephorm-1.0.1.dist-info/WHEEL +5 -0
  72. rephorm-1.0.1.dist-info/licenses/LICENSE +21 -0
  73. rephorm-1.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,93 @@
1
+ from fpdf import FPDF, enums
2
+
3
+ # Todo: The right place for this is mapper package.
4
+ def get_page_dimensions(pdf: FPDF):
5
+ return pdf.w, pdf.h
6
+
7
+ # Todo: The right place for this is mapper package.
8
+ # Todo: 03/31/2025: Kinda useless function. This could be done in the report mapper.
9
+
10
+ def set_title_page(pdf: FPDF, report_obj):
11
+
12
+ bool(report_obj.title) and set_title(pdf, report_obj)
13
+ bool(report_obj.abstract) and set_abstract(pdf, report_obj)
14
+ pdf.add_page()
15
+
16
+ def set_title(pdf: FPDF, report_obj):
17
+
18
+ title_height = report_obj.settings.styles["report"]["title"]["font_size"]
19
+
20
+ space_between = title_height
21
+
22
+ title_y_pos = pdf.eph / 2 - title_height / 2
23
+
24
+ pdf.set_y(title_y_pos)
25
+
26
+ pdf.set_font(report_obj.settings.styles["report"]["title"]["font_family"],
27
+ report_obj.settings.styles["report"]["title"]["font_style"],
28
+ report_obj.settings.styles["report"]["title"]["font_size"])
29
+
30
+ pdf.cell(
31
+ text=report_obj.title,
32
+ w=0,
33
+ align="C",
34
+ # Moves cursor to new ln, same behavior as in multi_cell,
35
+ # Necessary to get same space between, when using pdf.ln
36
+ new_y=enums.YPos.NEXT
37
+ )
38
+
39
+ pdf.ln(space_between)
40
+
41
+ pdf.set_font(report_obj.settings.styles["report"]["subtitle"]["font_family"],
42
+ report_obj.settings.styles["report"]["subtitle"]["font_style"],
43
+ report_obj.settings.styles["report"]["subtitle"]["font_size"])
44
+
45
+ pdf.multi_cell(
46
+ text=report_obj.subtitle,
47
+ w=0,
48
+ align="C",
49
+ )
50
+ pdf.ln(space_between)
51
+
52
+ if bool(report_obj.settings.logo):
53
+ logo_height = report_obj.settings.styles["report"]["logo_height"] # Todo: should get extracted to logo height - styles/params.!! Extract to styles
54
+ pdf.image(
55
+ report_obj.settings.logo,
56
+ x=enums.Align.C,
57
+ y=pdf.get_y(),
58
+ h=logo_height,
59
+ )
60
+
61
+ # reset the font
62
+ pdf.set_font(
63
+ family = report_obj.settings.styles["report"]["font_family"],
64
+ style = report_obj.settings.styles["report"]["font_style"],
65
+ )
66
+
67
+ def set_abstract(pdf: FPDF, report_obj):
68
+
69
+ rs = report_obj.settings.styles["report"]
70
+ abstract_y_pos = pdf.h - pdf.b_margin - rs["abstract"]["height"]
71
+ abstract_font_size= rs["abstract"]["font_size"]
72
+ abstract_text = report_obj.abstract
73
+
74
+ line_height = 1.5
75
+ pdf.set_font(family=rs["abstract"]["font_family"], size=abstract_font_size)
76
+
77
+ pdf.set_y(abstract_y_pos)
78
+
79
+ pdf.set_draw_color(0, 0, 0)
80
+ pdf.line(x1=pdf.l_margin, y1=abstract_y_pos - 5, x2=pdf.w-pdf.r_margin, y2=abstract_y_pos - 5)
81
+
82
+ b_margin = pdf.b_margin
83
+
84
+ pdf.set_auto_page_break(auto=False)
85
+
86
+ pdf.multi_cell(
87
+ text=abstract_text,
88
+ w=0,
89
+ h = abstract_font_size * line_height, # Todo consider extracting this 1.5 multiplier
90
+ align="l", # Todo: Consider extracting to styles
91
+ )
92
+
93
+ pdf.set_auto_page_break(auto=True, margin=b_margin)
@@ -0,0 +1,39 @@
1
+ from rephorm.dict.colors import color_codes
2
+
3
+
4
+ def resolve_color(color):
5
+
6
+ normalized_color = color.lower()
7
+
8
+ # Check if the input is within color_codes dict and if so - return hex code
9
+ if normalized_color in color_codes:
10
+ return color_codes[normalized_color]
11
+
12
+ # Hex validation
13
+ if normalized_color.startswith('#') and len(normalized_color) == 7:
14
+ try:
15
+ # raise a ValueError if not a valid hex
16
+ int(normalized_color[1:], 16)
17
+ return normalized_color
18
+ except ValueError:
19
+ pass
20
+
21
+ return color
22
+
23
+ # This function is used to resolve the highlight color for chart
24
+ # When it comes in natural language such as "green", it resolves
25
+ # based on our set of colors.
26
+ # In color_codes the value must be in hex, cannot be in RGB.
27
+ def resolve_highlight_color(color, alpha=1):
28
+ if color.lower().startswith(("#", "hsl", "rgb", "hsla", "rgba")):
29
+ return color
30
+ hex = resolve_color(color)
31
+ return hex_to_rgba(hex, alpha=alpha)
32
+
33
+ def hex_to_rgba(hex_color, alpha=1):
34
+
35
+ hex_color = hex_color.lstrip('#')
36
+ r = int(hex_color[0:2], 16)
37
+ g = int(hex_color[2:4], 16)
38
+ b = int(hex_color[4:6], 16)
39
+ return f"rgba({r}, {g}, {b}, {alpha})"
@@ -0,0 +1,71 @@
1
+ import irispie as ir
2
+ import re
3
+
4
+ from rephorm.utility.report.range_utility import get_highlight, get_span
5
+
6
+
7
+ def get_table_highlight(table):
8
+
9
+ start, end = get_highlight(table)
10
+ span = get_span(table)
11
+ skip_cols = 1
12
+ if table.settings.show_units:
13
+ skip_cols += 1
14
+
15
+ length = len(span.start >> end)
16
+
17
+ cols = range(list(span).index(start) + skip_cols, length + skip_cols)
18
+ cols = list(cols)
19
+
20
+ return cols
21
+
22
+ def prepare_row(
23
+ series: ir.Series = None,
24
+ span: ir.Span = None,
25
+ title: str = "",
26
+ unit: str = "",
27
+ show_units: bool = None,
28
+ decimal_precision: int = None,
29
+ compare_style: str = None,
30
+ footnote_references = None,
31
+ ):
32
+ if series is None:
33
+ series_data = ir.Series()
34
+ decimal_precision = 0
35
+
36
+ else:
37
+ series_data = series
38
+
39
+ if isinstance(series_data, ir.Series):
40
+ series_data = series_data[span].flatten().tolist()
41
+ #if isinstance(series_data, TableSeries):
42
+ else:
43
+ series_data = series_data.data[span].flatten().tolist()
44
+
45
+
46
+ if span is None:
47
+ raise Exception("Span is missing.")
48
+
49
+ options = {
50
+ "diff": ("[", "]"),
51
+ "pct": ("(", ")"),
52
+ }
53
+
54
+ left, right = options.get(
55
+ compare_style,
56
+ ("", ""),
57
+ )
58
+
59
+ # descriptions = [f"{spacer}{title}{footnote_references.get(i, ' ')}" for i in range(len(series_data))]
60
+
61
+ descriptions = [f"{title}"]
62
+
63
+ if show_units:
64
+ descriptions = descriptions + [unit]
65
+
66
+
67
+ pattern = r"\bnan\b|\[nan\]|\(nan\)"
68
+
69
+ row = descriptions + [re.sub(pattern, "", f"{left}{x:.{decimal_precision}f}{right}") for x in series_data]
70
+
71
+ return row
@@ -0,0 +1,49 @@
1
+ import fpdf
2
+
3
+ def add_title_with_references(pdf, title, references, font_family, font_size, font_style, title_y, cell_width=None):
4
+
5
+ # default fall back
6
+ cell_width = cell_width or pdf.epw
7
+
8
+ # anchor_x - starting x coordinate
9
+ anchor_x = pdf.l_margin if cell_width == pdf.epw else pdf.get_x()
10
+
11
+ pdf.set_font(font_family, font_style, font_size)
12
+
13
+ actual_title_width = pdf.get_string_width(title)
14
+
15
+ center_x = anchor_x + (cell_width - actual_title_width) / 2
16
+
17
+ pdf.set_xy(center_x, title_y)
18
+
19
+ # should set this on report level (report mapper)
20
+ pdf.c_margin = 0
21
+
22
+ is_multiline = "\n" in title
23
+
24
+ # avoid auto-wrapping. Only break line if user specifies.
25
+ if is_multiline:
26
+ pdf.multi_cell(actual_title_width, None, title, align="C")
27
+ else:
28
+ pdf.cell(actual_title_width, None, title, align="C", new_y=fpdf.YPos.NEXT)
29
+
30
+ y_after_title=pdf.y
31
+
32
+ # Todo: References will not work if it is multiline and has newlines, because it sets ref_y to title_y, when for multiline it should set to last line start Y
33
+ # ref_x will not work as well ...
34
+
35
+ if references:
36
+ pdf.set_font_size(font_size*0.5)
37
+ spacing = 3 # Space between references
38
+
39
+ ref_x = center_x + actual_title_width + spacing
40
+
41
+ # Set references
42
+ for ref in references:
43
+ ref_text = str(f"[{ref}]")
44
+ pdf.set_xy(ref_x, title_y)
45
+ pdf.cell(pdf.get_string_width(ref_text), None, ref_text, 0, 0, "L")
46
+ ref_x += pdf.get_string_width(ref_text) + spacing
47
+
48
+ # return last y pos
49
+ return y_after_title # Todo: Check why not pdf.get_y() and pdf.y? Also check why I cant set last Y here and then use it later. why it breaks. Why we need to return this Y at all
@@ -0,0 +1,12 @@
1
+ def mm_to_px(mm, ppi):
2
+ """Converts millimeters to pixels given the pixels per inch (PPI)."""
3
+ return (mm / 25.4) * ppi
4
+ # return mm * 3.78
5
+
6
+ # Todo: make generic function that converts report units (whatever we get) to respective ones we need / to px
7
+
8
+
9
+ #pt is what overlay_pdfs uses
10
+ def mm_to_pt(mm):
11
+ """Converts millimeters to points."""
12
+ return mm * 2.83465
@@ -0,0 +1,41 @@
1
+ Metadata-Version: 2.4
2
+ Name: rephorm
3
+ Version: 1.0.1
4
+ Summary: Python package for generating PDF reports through code
5
+ Author-email: OGResearch <it@ogresearch.com>
6
+ Maintainer-email: Sergey Plotnikov <sergey.plotnikov@ogresearch.com>, Ngoc Nam Nguyen <nam.nguyen@ogresearch.com>, Martynas Vycas <martynas.vycas@ogresearch.com>
7
+ License: MIT License
8
+
9
+ Copyright (c) 2025 OGResearch
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Classifier: Intended Audience :: Financial and Insurance Industry
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: Operating System :: OS Independent
32
+ Requires-Python: >=3.12
33
+ License-File: LICENSE
34
+ Requires-Dist: irispie>=0.61.0
35
+ Requires-Dist: fpdf2>=2.7.9
36
+ Requires-Dist: PyMuPDF>=1.25.1
37
+ Requires-Dist: twine==6.1.0
38
+ Requires-Dist: pkginfo>=1.12.1.2
39
+ Requires-Dist: kaleido==0.1.0post1; platform_system == "Windows"
40
+ Requires-Dist: kaleido==0.2.1; platform_system != "Windows"
41
+ Dynamic: license-file
@@ -0,0 +1,73 @@
1
+ rephorm/__init__.py,sha256=Bk6Ri5wmhyKe6nihc4_qDgEgxw0dOz5PY4o4q1hBh7U,661
2
+ rephorm/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ rephorm/decorators/settings_validation.py,sha256=FEikLkxMgiPGzSTeF6dJmu4mBPAU8dvy-EFFWVj9KDY,1973
4
+ rephorm/dict/__init__.py,sha256=M0NZuQ7-112l8K2h1eayVvSmvQrufrOcD5AYKgIf_Is,1
5
+ rephorm/dict/colors.py,sha256=JXhPiLwzk_IGwbk26mNXqiSOOcHhx0O1-EFMsVRyMwE,649
6
+ rephorm/dict/legend_positions.py,sha256=Tn9LWo34md63MtlXWGU7C_fIH4P-s6OLTybAUFk_PC8,3188
7
+ rephorm/dict/styles.py,sha256=ip3XduiYrGsUoHQCFTcpcU0D1QtuQNFO-NYVvGDhSAk,6526
8
+ rephorm/dict/update_layout.py,sha256=A8p9ExcvTAmhSL0bBIfwdxYdsN36K82aXYAGjDuMgGY,7201
9
+ rephorm/dict/update_traces.py,sha256=VFbBoIjLV5qba3MrHgiDFeKslFADRploLZytx4lDjrs,2836
10
+ rephorm/object_mappers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ rephorm/object_mappers/_globals.py,sha256=FnyT7yPXjUpt5A_18l8WFAguaihAdwvay_0Sg0Gm4sA,285
12
+ rephorm/object_mappers/chapter_mapper.py,sha256=yPaa4GUkVlA1obPQ3jsRpO774Y8j7Vh6cbKQ-x9O3Ig,4007
13
+ rephorm/object_mappers/chart_mapper.py,sha256=lUOCLXGyol47OxAALCYQxy6hF4DjvJJkhf0fBGxx7tw,4726
14
+ rephorm/object_mappers/chart_series_mapper.py,sha256=bAO-rNSoczV0hDo_Vhsv8F9robtu2TQ6WwHiX90jyFA,1915
15
+ rephorm/object_mappers/grid_mapper.py,sha256=gbuZF-vS9SAZyGLC0hfGV9snGPs8LKS7ZiY0wwtdKNQ,4650
16
+ rephorm/object_mappers/page_break_mapper.py,sha256=3db07DBaFgwMcizexmHOJIBQWg2zEvNJZb4rcyGL_sw,185
17
+ rephorm/object_mappers/report_mapper.py,sha256=FOgJiOSLecV9VFnEQhe3nftwnSLBlx_RpV1e2wFBdMs,3081
18
+ rephorm/object_mappers/table_mapper.py,sha256=Rda0cSmzNsD2kcZkIgVu3W6-YDZ9swgfV_qcF31rew4,7621
19
+ rephorm/object_mappers/table_section_mapper.py,sha256=9rAeTipDAtdlrFT_YiF85HenFEaMf4_d-Kt8rHc9o-Q,1396
20
+ rephorm/object_mappers/table_series_mapper.py,sha256=b9jAnkE7vt1kIX9u5RNzYgaORgqmK40C1Te6Gmx3nCU,2987
21
+ rephorm/object_mappers/text_mapper.py,sha256=XeKcnukceFVy2eJvIxTzwioC3G0rRsMAivfcCZiU5lo,1342
22
+ rephorm/object_mappers/_utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ rephorm/object_mappers/_utilities/chart_mapper_utility.py,sha256=UAywPZ-UTgUX-8L9QbshX-ySmAYlF9nYKvM8CUNa3_E,1229
24
+ rephorm/object_mappers/_utilities/grid_mapper_utility.py,sha256=1SeQOPQHqkgOvB9Bl-Qm6dkwmpcLLuCRrfb_WLtL4rI,323
25
+ rephorm/object_mappers/_utilities/table_mapper_utility.py,sha256=rVez9ldfufxEdKAzWuqVd3v8OXaBGM1Vo8kfJQW0ymc,2596
26
+ rephorm/object_params/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ rephorm/object_params/settings.py,sha256=_NG5CpSpBg6IKCpF_64tBepdRRAcNMOuqXoQY1u_IqQ,4969
28
+ rephorm/objects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
+ rephorm/objects/chapter.py,sha256=kNjor9eP5j5vLeWQjWHiz2o0driofhlqP0BdPTIthvo,1772
30
+ rephorm/objects/chart.py,sha256=kOuZW-_QaIwhlaYq5R9UItDGWM594wSwNhc5TxYgJts,3466
31
+ rephorm/objects/chart_series.py,sha256=1HqbuXng8bKgcucEKNdU1ADgyaa8JQpt8i5dPdxkYzE,2139
32
+ rephorm/objects/footnote.py,sha256=YmCsdlkwnAXV1lvrt2k7ADhYenRvZEcecUxsya0s2JY,274
33
+ rephorm/objects/grid.py,sha256=OT1lenrXLQAkrFSBm_hDTPtPtvJA0IDlMvIOxXfaAZo,2306
34
+ rephorm/objects/page_break.py,sha256=vnt33zhvtZMnbjNNw3rB4cQ6YaaFF64XNdYM3wGTn5Y,257
35
+ rephorm/objects/report.py,sha256=yOlLfEatJer830S9MSkxMNXix3X39kY4TcK4etMWxrQ,9505
36
+ rephorm/objects/table.py,sha256=uIv7BQOwt0KgsWuBPH0Ch_z521_Ory8SvAT8o6EJ4fE,3235
37
+ rephorm/objects/table_section.py,sha256=U5wIhTbxZOpubv2BqtO_Z_G9HSfQQLlwIAQVMe_00KI,2095
38
+ rephorm/objects/table_series.py,sha256=CvUr89_w0Am-swqrU0HwyrhiF3q1LzKv-0BtNwAAUXU,1773
39
+ rephorm/objects/text.py,sha256=9jczgU9-iXdNeE32V5e83axt8jk-QXdpm8b0FEOZR0g,847
40
+ rephorm/objects/_utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
+ rephorm/objects/_utilities/settings_container.py,sha256=ymsZCDX_hSDvn_tXENpjcEjb0DjsWwyf6qb9NH_U8L0,223
42
+ rephorm/utility/PDF.py,sha256=e5VqLLQ1MEEni8OSvlD2TP7UiP5HAPnUF0Sc-CPwbro,2564
43
+ rephorm/utility/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
+ rephorm/utility/add_style_prefix.py,sha256=6seaRcA-8hpCQH2NaKXKcjvBujPVsE9m8zlbzBrhOn8,891
45
+ rephorm/utility/is_set.py,sha256=j2JYEVmXNeGD3apPBnNiiN49OOLxz6rgeDSPPbbuQ4I,258
46
+ rephorm/utility/unit_converter.py,sha256=8VygJOpo8etmKi3kjQOdTaBcgsHU1YV3aDX34gUjyzE,375
47
+ rephorm/utility/fonts/OpenSans-Bold.ttf,sha256=vHPEXlgQoJcevq7062w13shGB9vgLaZ1f59D2Vi22l8,130860
48
+ rephorm/utility/fonts/OpenSans-BoldItalic.ttf,sha256=tiGd9Fy-5vh25rKPZoNI4YB7H7mtEY6n1ocEHw0zI4Q,136360
49
+ rephorm/utility/fonts/OpenSans-Italic.ttf,sha256=XqvWf-PYtbXu5kUE6p5KXvdmW2Q1d-8Rfzwy_aZ80p8,136604
50
+ rephorm/utility/fonts/OpenSans.ttf,sha256=ZTBIAnfaYu_eBH6ybnin5TLRz67skWA-aNY4drlmnw0,130832
51
+ rephorm/utility/fonts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ rephorm/utility/fonts/font_loading.py,sha256=l_ljfj_GSmjyKDYxx-I1KQJ57asMyhSUV1gC3lC4jBY,2087
53
+ rephorm/utility/merge/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ rephorm/utility/merge/chart_properties_manager.py,sha256=tMsqQqVwFiyCp2OGPk4FRGj6TSd2pqnwJKTNCAtdErs,3370
55
+ rephorm/utility/merge/merge_settings.py,sha256=2EGd93eGIBlGTPn7qY6ucRh4mgAK3YQRUPeA8CAXyQ4,6788
56
+ rephorm/utility/merge/merge_styles.py,sha256=X9jH9jLNpbTRGDwDq4efpsNPN8xZclM8U0QI-U0ARbY,2952
57
+ rephorm/utility/merge/pdf_merger.py,sha256=vCWifVRzML_fCqdDiqsDmoAi8uRF8dGevSMXmLtZoZs,1118
58
+ rephorm/utility/report/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
+ rephorm/utility/report/add_footnotes.py,sha256=gF4UketURzBQXaTumSnbOGo7tfWdVDvbgQ4Sv2UFuHY,1721
60
+ rephorm/utility/report/cleanup_utility.py,sha256=WEnINuGFUI0btSTchWlDexWUuEP432Y4JLUPlXxGnG0,582
61
+ rephorm/utility/report/footnotes_counter.py,sha256=82uNVCkM9sM72btLy7Pc6vIY3I8y5PgkkT-szxUJ17k,407
62
+ rephorm/utility/report/image_utility.py,sha256=2u5NEgQscG-ZtZQ0j8Oh-yuz4L3gF2hxBMijr5vSlmw,527
63
+ rephorm/utility/report/layout_utility.py,sha256=qRf8Rq9MdnVot1lRTiUMkVBBVdC1_kzExkf_u0Jkoro,2197
64
+ rephorm/utility/report/range_utility.py,sha256=hKtfusxqR3JzQMBnUSCFvHKzBYQETgYRbOCVG7EpfXg,3090
65
+ rephorm/utility/report/report_utility.py,sha256=oG5HmpnUY1uU64fWSV6Tbr5v1xRCKLTq0VVAL7sz7do,2956
66
+ rephorm/utility/report/resolve_color.py,sha256=VMs3MHR8g1emzZZrB3nVetKHatNWq7_2PsZGHcAQOYQ,1220
67
+ rephorm/utility/report/table_utility.py,sha256=mMEnR8doZ1I0xR3Jq_55ols7zDXdJ0GRf_u5NnkH9qE,1659
68
+ rephorm/utility/report/title_utility.py,sha256=da2p6ad9nCm2RhUN09S9QxuE7H4sL3l5cA3llcDdVIo,1742
69
+ rephorm-1.0.1.dist-info/licenses/LICENSE,sha256=J7qNT6dA5AkN4QCfd9uPlNftEs8jRiulHfO1ESxE3GU,1067
70
+ rephorm-1.0.1.dist-info/METADATA,sha256=pHLRBVPVh03M4wdJ9CMY0mV6GnfT06-ovNv_ayrjhRw,2072
71
+ rephorm-1.0.1.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
72
+ rephorm-1.0.1.dist-info/top_level.txt,sha256=akVppyH53yfIlJ5BbtNzKZF4306s-1XJycsOZOhDbQ0,8
73
+ rephorm-1.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.4.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 OGResearch
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.
@@ -0,0 +1 @@
1
+ rephorm