mergeron 2024.739079.11__py3-none-any.whl → 2024.739079.13__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.

Potentially problematic release.


This version of mergeron might be problematic. Click here for more details.

mergeron/__init__.py CHANGED
@@ -11,7 +11,7 @@ from numpy.typing import NDArray
11
11
 
12
12
  _PKG_NAME: str = Path(__file__).parent.stem
13
13
 
14
- VERSION = "2024.739079.11"
14
+ VERSION = "2024.739079.13"
15
15
 
16
16
  __version__ = VERSION
17
17
 
@@ -4,6 +4,13 @@ the third-party package, `xlsxwriter`.
4
4
 
5
5
  Includes a flexible system of defining cell formats.
6
6
 
7
+ NOTES
8
+ -----
9
+
10
+ This module is desinged for producing formatted summary output. For
11
+ writing bulk data to Excel, facilities provided in third-party packages
12
+ such as `polars` likely provide better performance.
13
+
7
14
  """
8
15
 
9
16
  from __future__ import annotations
@@ -31,7 +38,11 @@ class CFmt(dict, Enum): # type: ignore
31
38
  as xlsxWriter.Workbook.Format objects for writing
32
39
  cell values to formatted cells in a spreadsheet.
33
40
 
34
- See, https://xlsxwriter.readthedocs.io/format.html
41
+ NOTES
42
+ -----
43
+
44
+ For more information about xlsxwriter's cell formats,
45
+ see, https://xlsxwriter.readthedocs.io/format.html
35
46
  """
36
47
 
37
48
  XL_DEFAULT: ClassVar = {"font_name": "Calibri", "font_size": 11}
@@ -71,16 +82,101 @@ class CFmt(dict, Enum): # type: ignore
71
82
  HDR_BORDER: ClassVar = TOP_BORDER | BOT_BORDER
72
83
 
73
84
 
74
- def matrix_to_sheet(
85
+ def write_header(
86
+ _xl_sheet: xlsxwriter.worksheet.Worksheet,
87
+ /,
88
+ *,
89
+ center_header: str | None = None,
90
+ left_header: str | None = None,
91
+ right_header: str | None = None,
92
+ ) -> None:
93
+ """Write header text to given worksheet.
94
+
95
+ Parameters
96
+ ----------
97
+ _xl_sheet
98
+ Worksheet object
99
+ center_header
100
+ Text for center header
101
+ left_header
102
+ Text for left header
103
+ right_header
104
+ Text for right header
105
+
106
+ Raises
107
+ ------
108
+ ValueError
109
+ Must specify at least one header
110
+
111
+ Returns
112
+ -------
113
+ None
114
+ """
115
+ if not any((center_header, left_header, right_header)):
116
+ raise ValueError("must specify at least one header")
117
+ _xl_sheet.set_footer(
118
+ "".join([
119
+ f"&L{left_header}" if left_header else "",
120
+ f"&C{center_header}" if center_header else "",
121
+ f"&R{right_header}" if right_header else "",
122
+ ])
123
+ )
124
+
125
+
126
+ def write_footer(
127
+ _xl_sheet: xlsxwriter.worksheet.Worksheet,
128
+ /,
129
+ *,
130
+ center_footer: str | None = None,
131
+ left_footer: str | None = None,
132
+ right_footer: str | None = None,
133
+ ) -> None:
134
+ """Write footer text to given worksheet.
135
+
136
+ Parameters
137
+ ----------
138
+ _xl_sheet
139
+ Worksheet object
140
+ center_footer
141
+ Text for center footer
142
+ left_footer
143
+ Text for left footer
144
+ right_footer
145
+ Text for right footer
146
+
147
+ Raises
148
+ ------
149
+ ValueError
150
+ Must specify at least one footer
151
+
152
+ Returns
153
+ -------
154
+ None
155
+ """
156
+
157
+ if not any((center_footer, left_footer, right_footer)):
158
+ raise ValueError("must specify at least one footer")
159
+
160
+ _xl_sheet.set_footer(
161
+ "".join([
162
+ f"&L{left_footer}" if left_footer else "",
163
+ f"&C{center_footer}" if center_footer else "",
164
+ f"&R{right_footer}" if right_footer else "",
165
+ ])
166
+ )
167
+
168
+
169
+ def array_to_sheet(
75
170
  _xl_book: xlsxwriter.workbook.Workbook,
76
171
  _xl_sheet: xlsxwriter.worksheet.Worksheet,
77
- _data_table: npt.ArrayLike,
172
+ _data_table: Sequence[Any] | npt.NDArray[Any],
78
173
  _row_id: int,
79
174
  _col_id: int = 0,
80
175
  /,
81
176
  *,
82
177
  cell_format: Sequence[CFmt] | CFmt | None = None,
83
178
  green_bar_flag: bool = True,
179
+ ragged_flag: bool = True,
84
180
  ) -> tuple[int, int]:
85
181
  """
86
182
  Write a 2-D array to a worksheet.
@@ -111,51 +207,44 @@ def matrix_to_sheet(
111
207
  green_bar_flag
112
208
  Whether to highlight alternating rows as in green bar paper
113
209
 
210
+ Raises
211
+ ------
212
+ ValueError
213
+ If format tuple does not match data in length
214
+
114
215
  Returns
115
216
  -------
116
- Tuple giving address of cell (at left) below range written
217
+ Tuple giving address of cell at right below and after range written
117
218
 
118
219
  """
119
- _data_array: npt.NDArray[Any] = np.array(_data_table)
120
- del _data_table
121
-
122
- if not len(_data_array.shape) == 2:
123
- raise ValueError(
124
- "Array to write must be a 2-D array, but"
125
- f"the given array has shape, {_data_array.shape}."
126
- )
127
220
 
128
221
  # Get the array dimensions and row and column numbers for Excel
129
- _bottom_row_id: int = _row_id + _data_array.shape[0]
130
- _right_column_id: int = _col_id + _data_array.shape[1]
222
+ _num_rows = len(_data_table)
223
+ _bottom_row_id = _row_id + _num_rows
224
+ _num_cols = len(_data_table[0])
225
+ _right_column_id = _col_id + _num_cols
131
226
 
132
227
  if isinstance(cell_format, tuple):
133
228
  ensure_cell_format_spec_tuple(cell_format)
134
- if not len(cell_format) == len(_data_array[0]):
229
+ if not len(cell_format) == len(_data_table[0]):
135
230
  raise ValueError("Format tuple does not match data in length.")
136
231
  _cell_format: Sequence[CFmt] = cell_format
137
232
  elif isinstance(cell_format, CFmt):
138
- _cell_format = (cell_format,) * len(_data_array[0])
233
+ _cell_format = (cell_format,) * len(_data_table[0])
139
234
  else:
140
- _cell_format = (CFmt.XL_DEFAULT,) * len(_data_array[0])
141
-
142
- for _cell_row in range(_row_id, _bottom_row_id):
143
- for _cell_col in range(_col_id, _right_column_id):
144
- _cell_fmt = (
145
- (_cell_format[_cell_col - _col_id], CFmt.BAR_FILL)
146
- if green_bar_flag and (_cell_row - _row_id) % 2
147
- else _cell_format[_cell_col - _col_id]
148
- )
235
+ _cell_format = (CFmt.XL_DEFAULT,) * len(_data_table[0])
149
236
 
237
+ for _ri, _rv in enumerate(_data_table):
238
+ for _ci, _cv in enumerate(_rv):
239
+ _cell_fmt = _cell_format[_ci] | (
240
+ CFmt.BAR_FILL if green_bar_flag and _ri % 2 else {}
241
+ )
150
242
  scalar_to_sheet(
151
- _xl_book,
152
- _xl_sheet,
153
- _cell_row,
154
- _cell_col,
155
- _data_array[_cell_row - _row_id, _cell_col - _col_id],
156
- _cell_fmt,
243
+ _xl_book, _xl_sheet, _row_id + _ri, _col_id + _ci, _cv, _cell_fmt
157
244
  )
158
245
 
246
+ _right_column_id = _col_id + _ci + 1 if _ci > _num_cols else _right_column_id
247
+
159
248
  return _bottom_row_id, _right_column_id
160
249
 
161
250
 
@@ -186,6 +275,17 @@ def scalar_to_sheet(
186
275
  cell format, or the column-part of the 'R1,C1' address along with
187
276
  cell value and cell format.
188
277
 
278
+ Raises
279
+ ------
280
+ ValueError
281
+ If too many or too few arguments
282
+ ValueError
283
+ If incorrect/incomplete specification for Excel cell data
284
+
285
+ Returns
286
+ -------
287
+ None
288
+
189
289
  """
190
290
 
191
291
  if isinstance(_cell_addr_0, str):
@@ -201,9 +301,16 @@ def scalar_to_sheet(
201
301
  _cell_val = _s2s_args[1]
202
302
  _cell_fmt = _s2s_args[2] if len(_s2s_args) == 3 else None # type: ignore
203
303
  else:
204
- raise ValueError("Incorrect specification for Excel cell data.")
304
+ raise ValueError("Incorrect/incomplete specification for Excel cell data.")
205
305
 
206
- _xl_sheet.write(*_cell_addr, _cell_val, xl_fmt(_xl_book, _cell_fmt))
306
+ if isinstance(_cell_val, str):
307
+ _xl_sheet.write_string(*_cell_addr, _cell_val, xl_fmt(_xl_book, _cell_fmt))
308
+ else:
309
+ _xl_sheet.write(
310
+ *_cell_addr,
311
+ repr(_cell_val) if np.ndim(_cell_val) else _cell_val,
312
+ xl_fmt(_xl_book, _cell_fmt),
313
+ )
207
314
 
208
315
 
209
316
  def xl_fmt(
@@ -247,6 +354,11 @@ def ensure_cell_format_spec_tuple(_cell_formats: Sequence[CFmt], /) -> None:
247
354
  _cell_formats
248
355
  Format specification
249
356
 
357
+ Raises
358
+ ------
359
+ ValueError
360
+ If format specification is not tuple of CFmt aenums
361
+
250
362
  Returns
251
363
  -------
252
364
  True if format specification passes, else False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mergeron
3
- Version: 2024.739079.11
3
+ Version: 2024.739079.13
4
4
  Summary: Merger Policy Analysis using Python
5
5
  License: MIT
6
6
  Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
@@ -1,8 +1,8 @@
1
1
  mergeron/License.txt,sha256=7iX-y0EyjkbVJKJLS4ZKzuuE1wd0lryfsD_IytLG8lQ,1246
2
- mergeron/__init__.py,sha256=0Hhq1iav_yCwfkA-U_CFQPz6SYgpTtOAq3pNVm6JjHI,1648
2
+ mergeron/__init__.py,sha256=LCTDy3JKYCbKAjEFxXbRWUjibgwXwh3TdiB59cfqw2k,1648
3
3
  mergeron/core/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
4
4
  mergeron/core/damodaran_margin_data.py,sha256=pjI1rSK_O1-3Oel5b9KXH6ctnInjX1Vii7fypt00gV8,8541
5
- mergeron/core/excel_helper.py,sha256=d6PFfGCABXskaEb2m2GJ_oPRhz6axshUepq6fH8QWno,8010
5
+ mergeron/core/excel_helper.py,sha256=FfepqRVHzwkMVnXTwixNuc8OZFylJUh-oWTvBLXDLtQ,10444
6
6
  mergeron/core/ftc_merger_investigations_data.py,sha256=ZaV2DO7UZabV8eX0Ubq_ToIor7tIRzcvYC54ADliuTk,27931
7
7
  mergeron/core/guidelines_boundaries.py,sha256=__OHme8aGtwOgRXKp56WdX7k4vssAVQ8Ub54XwpS7mg,15621
8
8
  mergeron/core/guidelines_boundary_functions.py,sha256=rXjncqTn7NPgI2KY9Wuv3WNrsjmv74hpH9-mUI56NgQ,29714
@@ -31,6 +31,6 @@ mergeron/gen/enforcement_stats.py,sha256=1Mrx2p2-tXN9RdUQgRyk25xPvwh42EtjUHQgHMd
31
31
  mergeron/gen/market_sample.py,sha256=4AxzF8WYPsfZaWGMtm0LMkLrEPSgRUNXd_z_ddP9-vE,2303
32
32
  mergeron/gen/upp_tests.py,sha256=U2smV53VBnORIQpn3KCSdneSyegrq4dq-zT_6Eg-PIE,17302
33
33
  mergeron/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
34
- mergeron-2024.739079.11.dist-info/METADATA,sha256=C11ABRt4bVPnXJRpJKxeD_rMSAJIdTzEPuwWdLVhyUM,8691
35
- mergeron-2024.739079.11.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
36
- mergeron-2024.739079.11.dist-info/RECORD,,
34
+ mergeron-2024.739079.13.dist-info/METADATA,sha256=4Dwvb55YuJxkmLfs-01LzDMpN2fhPOVUKh1--38UwTs,8691
35
+ mergeron-2024.739079.13.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
36
+ mergeron-2024.739079.13.dist-info/RECORD,,